Compare commits
6 Commits
d104222fdd
...
f07a360da2
| Author | SHA1 | Date |
|---|---|---|
|
|
f07a360da2 | |
|
|
a79d50e6e8 | |
|
|
7cb64515bd | |
|
|
e768497cfd | |
|
|
b9d35cbd4e | |
|
|
ab2d39407c |
|
|
@ -17,7 +17,7 @@ namespace matador::backends::postgres {
|
|||
postgres_connection::string_to_int_map postgres_connection::statement_name_map_{};
|
||||
|
||||
postgres_connection::postgres_connection(const sql::connection_info &info)
|
||||
: connection_impl(info) {
|
||||
: connection_impl(info) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> postgres_connection::open() {
|
||||
|
|
@ -93,16 +93,17 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
|
|||
|
||||
const int num_col = PQnfields(res);
|
||||
if (prototype.size() != static_cast<size_t>(num_col)) {
|
||||
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Number of received columns doesn't match expected columns.", context.sql));
|
||||
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_,
|
||||
"Number of received columns doesn't match expected columns.", context.sql));
|
||||
}
|
||||
for (int i = 0; i < num_col; ++i) {
|
||||
if (!prototype.at(i).is_null()) {
|
||||
continue;
|
||||
}
|
||||
const auto type = oid2type(PQftype(res, i));
|
||||
// const char *col_name = PQfname(res, i);
|
||||
// const auto size = PQfmod(res, i);
|
||||
prototype.at(i).change_type(type);
|
||||
if (!prototype.at(i).is_null()) {
|
||||
continue;
|
||||
}
|
||||
const auto type = oid2type(PQftype(res, i));
|
||||
// const char *col_name = PQfname(res, i);
|
||||
// const auto size = PQfmod(res, i);
|
||||
prototype.at(i).change_type(type);
|
||||
}
|
||||
|
||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), prototype));
|
||||
|
|
@ -122,11 +123,11 @@ std::string postgres_connection::generate_statement_name(const sql::query_contex
|
|||
return name.str();
|
||||
}
|
||||
|
||||
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> postgres_connection::prepare(const sql::query_context &context) {
|
||||
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> postgres_connection::prepare(
|
||||
const sql::query_context &context) {
|
||||
auto statement_name = generate_statement_name(context);
|
||||
|
||||
const PGresult *result = PQprepare(conn_, statement_name.c_str(), context.sql.c_str(),
|
||||
static_cast<int>(context.bind_vars.size()), nullptr);
|
||||
const PGresult *result = PQprepare(conn_, statement_name.c_str(), context.sql.c_str(), static_cast<int>(context.bind_vars.size()), nullptr);
|
||||
|
||||
if (is_result_error(result)) {
|
||||
return utils::failure(make_error(sql::error_code::PREPARE_FAILED, result, conn_, "Failed to prepare", context.sql));
|
||||
|
|
@ -139,8 +140,7 @@ utils::result<std::unique_ptr<sql::statement_impl>, utils::error> postgres_conne
|
|||
utils::result<size_t, utils::error> postgres_connection::execute(const std::string &stmt) {
|
||||
PGresult *res = PQexec(conn_, stmt.c_str());
|
||||
|
||||
if (const auto status = PQresultStatus(res); status != PGRES_COMMAND_OK &&
|
||||
status != PGRES_TUPLES_OK) {
|
||||
if (const auto status = PQresultStatus(res); status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
|
||||
return utils::failure(make_error(sql::error_code::FAILURE, res, conn_, "Failed to execute", stmt));
|
||||
}
|
||||
|
||||
|
|
@ -152,64 +152,75 @@ utils::result<size_t, utils::error> postgres_connection::execute(const std::stri
|
|||
}
|
||||
|
||||
utils::basic_type oid2type(const Oid oid) {
|
||||
switch (oid) {
|
||||
case 16:
|
||||
return utils::basic_type::Boolean;
|
||||
case 17:
|
||||
return utils::basic_type::Blob;
|
||||
case 18:
|
||||
return utils::basic_type::Int8;
|
||||
case 21:
|
||||
return utils::basic_type::Int16;
|
||||
case 23:
|
||||
return utils::basic_type::Int32;
|
||||
case 20:
|
||||
return utils::basic_type::Int64;
|
||||
case 25:
|
||||
return utils::basic_type::Text;
|
||||
case 1043:
|
||||
return utils::basic_type::Varchar;
|
||||
case 700:
|
||||
return utils::basic_type::Float;
|
||||
case 701:
|
||||
return utils::basic_type::Double;
|
||||
case 1082:
|
||||
return utils::basic_type::Date;
|
||||
case 1114:
|
||||
return utils::basic_type::Time;
|
||||
default:
|
||||
return utils::basic_type::Null;
|
||||
}
|
||||
switch (oid) {
|
||||
case 16:
|
||||
return utils::basic_type::Boolean;
|
||||
case 17:
|
||||
return utils::basic_type::Blob;
|
||||
case 18:
|
||||
return utils::basic_type::Int8;
|
||||
case 21:
|
||||
return utils::basic_type::Int16;
|
||||
case 23:
|
||||
return utils::basic_type::Int32;
|
||||
case 20:
|
||||
return utils::basic_type::Int64;
|
||||
case 25:
|
||||
return utils::basic_type::Text;
|
||||
case 1043:
|
||||
return utils::basic_type::Varchar;
|
||||
case 700:
|
||||
return utils::basic_type::Float;
|
||||
case 701:
|
||||
return utils::basic_type::Double;
|
||||
case 1082:
|
||||
return utils::basic_type::Date;
|
||||
case 1114:
|
||||
return utils::basic_type::Time;
|
||||
default:
|
||||
return utils::basic_type::Null;
|
||||
}
|
||||
}
|
||||
|
||||
utils::basic_type string2type(const char *type) {
|
||||
if (strcmp(type, "int2") == 0) {
|
||||
return utils::basic_type::Int16;
|
||||
} else if (strcmp(type, "int4") == 0) {
|
||||
return utils::basic_type::Int32;
|
||||
} else if (strcmp(type, "int8") == 0) {
|
||||
return utils::basic_type::Int64;
|
||||
} else if (strcmp(type, "bool") == 0) {
|
||||
return utils::basic_type::Boolean;
|
||||
} else if (strcmp(type, "date") == 0) {
|
||||
return utils::basic_type::Date;
|
||||
} else if (strcmp(type, "timestamp") == 0) {
|
||||
return utils::basic_type::Time;
|
||||
} else if (strcmp(type, "float4") == 0) {
|
||||
return utils::basic_type::Float;
|
||||
} else if (strcmp(type, "float8") == 0) {
|
||||
return utils::basic_type::Double;
|
||||
} else if (strncmp(type, "varchar", 7) == 0) {
|
||||
return utils::basic_type::Varchar;
|
||||
} else if (strcmp(type, "character varying") == 0) {
|
||||
return utils::basic_type::Varchar;
|
||||
} else if (strcmp(type, "text") == 0) {
|
||||
return utils::basic_type::Text;
|
||||
} else if (strcmp(type, "bytea") == 0) {
|
||||
return utils::basic_type::Blob;
|
||||
} else {
|
||||
return utils::basic_type::Null;
|
||||
}
|
||||
if (strcmp(type, "int4") == 0) {
|
||||
return utils::basic_type::Int32;
|
||||
}
|
||||
if (strcmp(type, "int8") == 0) {
|
||||
return utils::basic_type::Int64;
|
||||
}
|
||||
if (strcmp(type, "bool") == 0) {
|
||||
return utils::basic_type::Boolean;
|
||||
}
|
||||
if (strcmp(type, "date") == 0) {
|
||||
return utils::basic_type::Date;
|
||||
}
|
||||
if (strcmp(type, "timestamp") == 0) {
|
||||
return utils::basic_type::Time;
|
||||
}
|
||||
if (strcmp(type, "float4") == 0) {
|
||||
return utils::basic_type::Float;
|
||||
}
|
||||
if (strcmp(type, "float8") == 0) {
|
||||
return utils::basic_type::Double;
|
||||
}
|
||||
if (strncmp(type, "varchar", 7) == 0) {
|
||||
return utils::basic_type::Varchar;
|
||||
}
|
||||
if (strcmp(type, "character varying") == 0) {
|
||||
return utils::basic_type::Varchar;
|
||||
}
|
||||
if (strcmp(type, "text") == 0) {
|
||||
return utils::basic_type::Text;
|
||||
}
|
||||
if (strcmp(type, "bytea") == 0) {
|
||||
return utils::basic_type::Blob;
|
||||
}
|
||||
|
||||
return utils::basic_type::Null;
|
||||
}
|
||||
|
||||
utils::result<std::vector<object::attribute>, utils::error> postgres_connection::describe(const std::string &table) {
|
||||
|
|
@ -251,10 +262,12 @@ utils::result<std::vector<object::attribute>, utils::error> postgres_connection:
|
|||
return utils::ok(prototype);
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> postgres_connection::exists(const std::string &schema_name, const std::string &table_name) {
|
||||
const std::string stmt(
|
||||
"SELECT 1 FROM information_schema.tables WHERE table_schema = '" + schema_name + "' AND table_name = '" + table_name
|
||||
+ "'");
|
||||
utils::result<bool, utils::error> postgres_connection::exists(const std::string &schema_name,
|
||||
const std::string &table_name) {
|
||||
std::string stmt("SELECT 1 FROM information_schema.tables WHERE table_name = '" + table_name + "'");
|
||||
if (!schema_name.empty()) {
|
||||
stmt += " AND table_schema = '" + schema_name + "'";
|
||||
}
|
||||
|
||||
PGresult *res = PQexec(conn_, stmt.c_str());
|
||||
|
||||
|
|
@ -269,14 +282,12 @@ utils::result<bool, utils::error> postgres_connection::exists(const std::string
|
|||
return utils::ok(*result == 1);
|
||||
}
|
||||
|
||||
std::string postgres_connection::to_escaped_string(const utils::blob& value) const
|
||||
{
|
||||
std::string postgres_connection::to_escaped_string(const utils::blob &value) const {
|
||||
size_t escapedDataLength;
|
||||
unsigned char *escapedData = PQescapeByteaConn(conn_, value.data(), value.size(), &escapedDataLength);
|
||||
|
||||
return {reinterpret_cast<char*>(escapedData), escapedDataLength-1};
|
||||
return {reinterpret_cast<char *>(escapedData), escapedDataLength - 1};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
add_executable(demo main.cpp
|
||||
object.cpp)
|
||||
add_executable(demo main.cpp)
|
||||
|
||||
target_link_libraries(demo PRIVATE
|
||||
matador-core
|
||||
matador-orm
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "matador/query/column.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/query_macro.hpp"
|
||||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/meta_table_macro.hpp"
|
||||
|
||||
#include "matador/object/object_ptr.hpp"
|
||||
#include "matador/object/repository.hpp"
|
||||
|
|
@ -11,12 +11,8 @@
|
|||
#include "matador/utils/access.hpp"
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
#include "matador/utils/enum_mapper.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include "matador/sql/query_macro.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
struct author {
|
||||
unsigned int id{};
|
||||
|
|
@ -144,20 +140,20 @@ struct matador::utils::data_type_traits<job::job_mode, void> {
|
|||
}
|
||||
};
|
||||
|
||||
QUERY_HELPER( authors, AUTHOR, id, first_name, last_name, date_of_birth, year_of_birth, distinguished )
|
||||
META_TABLE(authors, AUTHOR, id, first_name, last_name, date_of_birth, year_of_birth, distinguished)
|
||||
|
||||
QUERY_HELPER( books, BOOK, id, author_id, title, published_in )
|
||||
META_TABLE(books, BOOK, id, author_id, title, published_in)
|
||||
|
||||
QUERY_HELPER( job, JOB, id, payload, type, description, state, mode )
|
||||
META_TABLE(job, JOB, id, payload, type, description, state, mode)
|
||||
|
||||
QUERY_HELPER( payload, PAYLOAD, id )
|
||||
META_TABLE(payload, PAYLOAD, id )
|
||||
|
||||
QUERY_HELPER( temporary_table, TEMPORARY_TABLE, id );
|
||||
META_TABLE(temporary_table, TEMPORARY_TABLE, id );
|
||||
|
||||
QUERY_HELPER(customer, CUSTOMER, id, name, email, address)
|
||||
QUERY_HELPER(product, PRODUCT, id, title, description, price, category)
|
||||
QUERY_HELPER(category, CATEGORY, id, title, description)
|
||||
QUERY_HELPER(cart, CART, id, items, owner)
|
||||
META_TABLE(customer, CUSTOMER, id, name, email, address)
|
||||
META_TABLE(product, PRODUCT, id, title, description, price, category)
|
||||
META_TABLE(category, CATEGORY, id, title, description)
|
||||
META_TABLE(cart, CART, id, items, owner)
|
||||
|
||||
int main() {
|
||||
using namespace matador::sql;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define FOREIGN_NODE_COMPLETER_HPP
|
||||
|
||||
#include "matador/object/internal/shadow_repository.hpp"
|
||||
#include "matador/object/internal/observer_list_copy_creator.hpp"
|
||||
#include "matador/object/many_to_many_relation.hpp"
|
||||
#include "matador/object/repository_node.hpp"
|
||||
#include "matador/object/join_columns_collector.hpp"
|
||||
|
|
@ -35,9 +36,9 @@ private:
|
|||
using node_ptr = std::shared_ptr<repository_node>;
|
||||
|
||||
public:
|
||||
static void complete(const std::shared_ptr<repository_node> &node, Observers<NodeType>... observers) {
|
||||
static void complete(const std::shared_ptr<repository_node> &node, const std::vector<std::unique_ptr<observer<NodeType>>> &observers) {
|
||||
internal::shadow_repository shadow(node->repo_);
|
||||
foreign_node_completer completer(shadow, observers...);
|
||||
foreign_node_completer completer(shadow, observers);
|
||||
|
||||
completer.complete_node(node);
|
||||
}
|
||||
|
|
@ -77,11 +78,10 @@ public:
|
|||
static void on_has_many_to_many(const char * /*id*/, CollectionType &/*collection*/, const utils::foreign_attributes &/*attr*/) {}
|
||||
|
||||
private:
|
||||
explicit foreign_node_completer(internal::shadow_repository &shadow, Observers<NodeType>... observers)
|
||||
explicit foreign_node_completer(internal::shadow_repository &shadow, const std::vector<std::unique_ptr<observer<NodeType>>> &observers)
|
||||
: repo_(shadow)
|
||||
, log_(logger::create_logger("node_completer")) {
|
||||
// observers_.emplace_back(observers...);
|
||||
}
|
||||
, log_(logger::create_logger("node_completer"))
|
||||
, observers_(observers) {}
|
||||
|
||||
void complete_node(const std::shared_ptr<repository_node> &node) {
|
||||
nodes_.push(node);
|
||||
|
|
@ -91,75 +91,22 @@ private:
|
|||
nodes_.pop();
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void attach_node(const std::string &name) {
|
||||
if (repo_.contains(typeid(Type))) {
|
||||
return;
|
||||
}
|
||||
const auto node = repository_node::make_node<Type>(repo_.repo(), name);
|
||||
if (auto result = repo_.attach_node(node)) {
|
||||
foreign_node_completer<Type>::complete(result.value());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void attach_node() {
|
||||
if (repo_.contains(typeid(Type))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto node = repository_node::make_node<Type>(repo_.repo(), "", []{ return std::make_unique<Type>(); });
|
||||
if (auto result = repo_.attach_node(node)) {
|
||||
foreign_node_completer<Type>::complete(result.value());
|
||||
}
|
||||
}
|
||||
auto observers = internal::observer_list_copy_creator<NodeType, Type, Observers...>::copy_create(observers_);
|
||||
|
||||
template<typename Type>
|
||||
void attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column) {
|
||||
using relation_value_type = many_to_many_relation<Type, NodeType>;
|
||||
using value_type = Type;
|
||||
|
||||
// Check if the object_ptr type is already inserted in the schema (by id)
|
||||
auto result = repo_.find_node(typeid(value_type));
|
||||
if (!result) {
|
||||
// Todo: throw internal error or attach node
|
||||
if (repo_.is_node_announced(typeid(Type))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto foreign_node = result.value();
|
||||
result = repo_.find_node(name);
|
||||
if (result) {
|
||||
return;
|
||||
}
|
||||
// Relation does not exist. Create it.
|
||||
auto creator = [join_column, inverse_join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
auto node = repository_node::make_node<relation_value_type>(repo_.repo(), name, std::move(creator));
|
||||
result = repo_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
foreign_node_completer<relation_value_type>::complete(result.value());
|
||||
|
||||
// auto& node = result.value();
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(name, relation_type::HasMany, node);
|
||||
const auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, nodes_.top());
|
||||
const auto inverse_join_endpoint = std::make_shared<relation_endpoint>(inverse_join_column, relation_type::BelongsTo, foreign_node);
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>(name, relation_type::HasMany, node);
|
||||
// register relation endpoint in local node
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
// register relation endpoint in foreign node
|
||||
foreign_node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
// register endpoints in relation node
|
||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint);
|
||||
node->info_->register_relation_endpoint(typeid(value_type), inverse_join_endpoint);
|
||||
// link endpoints
|
||||
link_relation_endpoints(local_endpoint, join_endpoint);
|
||||
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
||||
const auto node = repository_node::make_node<Type>(repo_.repo(), "", []{ return std::make_unique<Type>(); }, std::move(observers));
|
||||
repo_.push_announce_node(typeid(Type), node);
|
||||
// if (auto result = repo_.attach_node(node)) {
|
||||
// foreign_node_completer<Type>::complete(result.value(), {});
|
||||
// }
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -178,7 +125,7 @@ private:
|
|||
internal::shadow_repository &repo_;
|
||||
logger::logger log_;
|
||||
join_columns_collector join_columns_collector_{};
|
||||
// const std::vector<Observers<NodeType>...> observers_;
|
||||
const std::vector<std::unique_ptr<observer<NodeType>>>& observers_;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -190,7 +137,7 @@ void foreign_node_completer<NodeType, Observers...>::on_belongs_to(const char *
|
|||
|
||||
template<typename NodeType, template<typename> typename ...Observers>
|
||||
template<class ForeignPointerType>
|
||||
void foreign_node_completer<NodeType, Observers...>::on_has_one(const char *, ForeignPointerType &, const utils::foreign_attributes &) {
|
||||
void foreign_node_completer<NodeType, Observers...>::on_has_one(const char * /*id*/, ForeignPointerType &, const utils::foreign_attributes &) {
|
||||
attach_node<typename ForeignPointerType::value_type>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef MATADOR_OBSERVER_LIST_COPY_CREATOR_HPP
|
||||
#define MATADOR_OBSERVER_LIST_COPY_CREATOR_HPP
|
||||
|
||||
#include "matador/object/observer.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace matador::object::internal {
|
||||
template <typename SourceType, typename DestType, template <typename> class... ObserverType>
|
||||
class observer_list_copy_creator
|
||||
{
|
||||
public:
|
||||
using source_observer_vector = std::vector<std::unique_ptr<observer<SourceType>>>;
|
||||
using observer_vector = std::vector<std::unique_ptr<observer<DestType>>>;
|
||||
using iterator = typename observer_vector::iterator;
|
||||
|
||||
static observer_vector copy_create(const source_observer_vector &source_observers) {
|
||||
observer_list_copy_creator creator(source_observers);
|
||||
|
||||
return std::move(creator.observers_);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit observer_list_copy_creator(const source_observer_vector &source_observers)
|
||||
: source_observers_(source_observers) {
|
||||
if constexpr (sizeof...(ObserverType) != 0) {
|
||||
copy_observer<ObserverType...>();
|
||||
}
|
||||
}
|
||||
|
||||
template <template <typename> class FirstObserverType>
|
||||
void copy_observer() {
|
||||
try_copy_observer<FirstObserverType>();
|
||||
}
|
||||
|
||||
template <template <typename> class FirstObserverType, template <typename> class NextObserverType, template <typename> class... RestObserverType>
|
||||
void copy_observer() {
|
||||
try_copy_observer<FirstObserverType>();
|
||||
copy_observer<NextObserverType, RestObserverType...>();
|
||||
}
|
||||
|
||||
template <template <typename> class CurrentObserverType>
|
||||
void try_copy_observer() {
|
||||
for ( const auto &obs : source_observers_ ) {;
|
||||
if (const auto *casted_observer = dynamic_cast<const CurrentObserverType<SourceType>*>(obs.get()); casted_observer != nullptr) {
|
||||
observers_.emplace_back(std::make_unique<CurrentObserverType<DestType>>(*casted_observer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
const source_observer_vector &source_observers_;
|
||||
observer_vector observers_;
|
||||
};
|
||||
}
|
||||
#endif //MATADOR_OBSERVER_LIST_COPY_CREATOR_HPP
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef MATADOR_OBSERVER_LIST_CREATOR_HPP
|
||||
#define MATADOR_OBSERVER_LIST_CREATOR_HPP
|
||||
|
||||
#include "matador/object/observer.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace matador::object::internal {
|
||||
template <typename Type, template <typename> class... ObserverType>
|
||||
class observer_list_creator
|
||||
{
|
||||
public:
|
||||
using observer_vector = std::vector<std::unique_ptr<observer<Type>>>;
|
||||
|
||||
static void create_missing(observer_vector &observers) {
|
||||
observer_list_creator creator(observers);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit observer_list_creator(observer_vector &observers)
|
||||
: observers_(observers) {
|
||||
if constexpr (sizeof...(ObserverType) != 0) {
|
||||
build_observer<ObserverType...>();
|
||||
}
|
||||
}
|
||||
|
||||
template <template <typename> class FirstObserverType>
|
||||
void build_observer() {
|
||||
try_copy_on_missing<FirstObserverType>();
|
||||
}
|
||||
|
||||
template <template <typename> class FirstObserverType, template <typename> class NextObserverType, template <typename> class... RestObserverType>
|
||||
void build_observer() {
|
||||
try_copy_on_missing<FirstObserverType>();
|
||||
build_observer<NextObserverType, RestObserverType...>();
|
||||
}
|
||||
|
||||
template <template <typename> class CurrentObserverType>
|
||||
void try_copy_on_missing() {
|
||||
bool is_missing{true};
|
||||
for ( const auto &obs : observers_ ) {;
|
||||
if (dynamic_cast<const CurrentObserverType<Type>*>(obs.get())) {
|
||||
is_missing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_missing) {
|
||||
append<CurrentObserverType<Type>>();
|
||||
}
|
||||
}
|
||||
|
||||
template <class CurrentObserverType>
|
||||
void append(std::enable_if_t<std::is_default_constructible_v<CurrentObserverType> || std::is_trivially_default_constructible_v<CurrentObserverType>>* = nullptr) {
|
||||
observers_.emplace_back(std::make_unique<CurrentObserverType>());
|
||||
}
|
||||
|
||||
template <class CurrentObserverType>
|
||||
void append(std::enable_if_t<!std::is_default_constructible_v<CurrentObserverType> && !std::is_trivially_default_constructible_v<CurrentObserverType>>* = nullptr) {
|
||||
static_assert("no default constructor");
|
||||
}
|
||||
|
||||
private:
|
||||
observer_vector &observers_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //MATADOR_OBSERVER_LIST_CREATOR_HPP
|
||||
|
|
@ -40,6 +40,11 @@ public:
|
|||
[[nodiscard]] std::shared_ptr<object> object_for_type(const std::type_index &ti) const;
|
||||
void remove_object_for_type(const std::type_index &ti) const;
|
||||
|
||||
[[nodiscard]] bool is_node_announced(const std::type_index &ti) const;
|
||||
void push_announce_node(const std::type_index &ti, const node_ptr &node) const;
|
||||
[[nodiscard]] node_ptr announce_node(const std::type_index &ti) const;
|
||||
[[nodiscard]] node_ptr pop_announce_node(const std::type_index &ti) const;
|
||||
|
||||
private:
|
||||
repository& repo_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,17 +51,17 @@ private:
|
|||
|
||||
class object_generator {
|
||||
private:
|
||||
explicit object_generator(repository& repo, const std::shared_ptr<object> &object);
|
||||
explicit object_generator(const repository& repo, const std::shared_ptr<object> &object);
|
||||
|
||||
public:
|
||||
template < class Type >
|
||||
static std::shared_ptr<object> generate(repository &repo, const std::string &name) {
|
||||
static std::shared_ptr<object> generate(const repository &repo, const std::string &name) {
|
||||
return generate(std::make_unique<Type>(), repo, name);
|
||||
}
|
||||
|
||||
template < class Type >
|
||||
static std::shared_ptr<object> generate(std::unique_ptr<Type>&& t, repository &repo, const std::string &name) {
|
||||
const internal::shadow_repository shadow_repo(repo);
|
||||
static std::shared_ptr<object> generate(std::unique_ptr<Type>&& t, const repository &repo, const std::string &name) {
|
||||
const internal::shadow_repository shadow_repo(const_cast<repository&>(repo));
|
||||
const std::type_index ti(typeid(Type));
|
||||
if (shadow_repo.has_object_for_type(ti)) {
|
||||
auto obj = shadow_repo.object_for_type(ti);
|
||||
|
|
@ -129,7 +129,7 @@ private:
|
|||
|
||||
static std::shared_ptr<object> acquire_object(repository &repo, const std::type_index &ti, const std::string& name);
|
||||
private:
|
||||
repository &repo_;
|
||||
const repository &repo_;
|
||||
std::shared_ptr<object> object_;
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ template<typename ValueType>
|
|||
void object_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) {
|
||||
auto &ref = emplace_attribute<ValueType>(id, { attr.size(), utils::constraints::PrimaryKey }, null_option_type::NotNull);
|
||||
prepare_primary_key(ref, utils::identifier(x));
|
||||
create_pk_constraint(id);
|
||||
// create_pk_constraint(id);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
|
|
@ -167,7 +167,7 @@ void object_generator::create_fk_constraint(const std::string& name) const {
|
|||
template<typename Type>
|
||||
std::shared_ptr<object> object_generator::fk_object() const {
|
||||
const auto ti = std::type_index(typeid(Type));
|
||||
const internal::shadow_repository shadow_repo(repo_);
|
||||
const internal::shadow_repository shadow_repo(const_cast<repository &>(repo_));
|
||||
if (const auto result = shadow_repo.basic_info(ti)) {
|
||||
return result->get().object();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,21 +9,21 @@
|
|||
namespace matador::object {
|
||||
class repository_node;
|
||||
|
||||
template<typename Type>
|
||||
class observer_ptr {
|
||||
public:
|
||||
explicit observer_ptr(std::unique_ptr<observer<Type>> &&observer)
|
||||
: observer(std::move(observer)) {}
|
||||
|
||||
operator bool() const { return observer != nullptr; }
|
||||
|
||||
observer<Type> *get() const { return observer.get(); }
|
||||
observer<Type> &operator*() const { return *observer; }
|
||||
observer<Type> *operator->() const { return observer.get(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<observer<Type>> observer;
|
||||
};
|
||||
// template<typename Type>
|
||||
// class observer_ptr {
|
||||
// public:
|
||||
// explicit observer_ptr(std::unique_ptr<observer<Type>> &&o)
|
||||
// : observer_(std::move(o)) {}
|
||||
//
|
||||
// operator bool() const { return observer_ != nullptr; }
|
||||
//
|
||||
// observer<Type> *get() const { return observer_.get(); }
|
||||
// observer<Type> &operator*() const { return *observer_; }
|
||||
// observer<Type> *operator->() const { return observer_.get(); }
|
||||
//
|
||||
// private:
|
||||
// std::unique_ptr<observer<Type>> observer_;
|
||||
// };
|
||||
template<typename Type>
|
||||
class object_info final : public basic_object_info {
|
||||
public:
|
||||
|
|
@ -31,10 +31,11 @@ public:
|
|||
|
||||
object_info(const std::shared_ptr<repository_node>& node,
|
||||
std::shared_ptr<class object> &&obj,
|
||||
std::vector<std::unique_ptr<observer<Type>>>&& observers,
|
||||
create_func&& creator)
|
||||
: basic_object_info(node, std::move(obj))
|
||||
, creator_(std::move(creator)){
|
||||
}
|
||||
, creator_(std::move(creator))
|
||||
, observers_(std::move(observers)){}
|
||||
|
||||
explicit object_info(const std::shared_ptr<repository_node>& node)
|
||||
: basic_object_info(node, {}) {
|
||||
|
|
@ -55,13 +56,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void register_observer(observer_ptr<Type> observer) {
|
||||
void register_observer(std::unique_ptr<observer<Type>>&& observer) {
|
||||
observers_.push_back(std::move(observer));
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<observer<Type>>>& observers() const {
|
||||
return observers_;
|
||||
}
|
||||
|
||||
private:
|
||||
Type prototype_;
|
||||
create_func creator_{[]{ return std::make_unique<Type>(); }};
|
||||
std::vector<observer_ptr<Type>> observers_;
|
||||
std::vector<std::unique_ptr<observer<Type>>> observers_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
* @param node The attached repository_node
|
||||
* @param prototype The prototype object of the attached node
|
||||
*/
|
||||
virtual void on_attach(repository_node &node, const Type &prototype) = 0;
|
||||
virtual void on_attach(const repository_node &node, const Type &prototype) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Called on repository_node detached
|
||||
|
|
@ -74,7 +74,7 @@ public:
|
|||
* @param node The to be detached repository_node
|
||||
* @param prototype The prototype object of the detached node
|
||||
*/
|
||||
virtual void on_detach(repository_node &node, const Type &prototype) = 0;
|
||||
virtual void on_detach(const repository_node &node, const Type &prototype) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Called on object insertion.
|
||||
|
|
@ -84,7 +84,7 @@ public:
|
|||
*
|
||||
* @param obj The proxy of the inserted object.
|
||||
*/
|
||||
virtual void on_insert(Type &obj) = 0;
|
||||
virtual void on_insert(const Type &obj) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called on object update.
|
||||
|
|
@ -94,7 +94,7 @@ public:
|
|||
*
|
||||
* @param obj The proxy of the updated object.
|
||||
*/
|
||||
virtual void on_update(Type &obj) = 0;
|
||||
virtual void on_update(const Type &obj) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called on object deletion.
|
||||
|
|
@ -104,7 +104,7 @@ public:
|
|||
*
|
||||
* @param obj The proxy of the deleted object.
|
||||
*/
|
||||
virtual void on_delete(Type &obj) = 0;
|
||||
virtual void on_delete(const Type &obj) = 0;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ private:
|
|||
* no has_many or belongs_to
|
||||
* invalid relation -> error
|
||||
*/
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
class relation_completer final {
|
||||
private:
|
||||
using node_ptr = std::shared_ptr<repository_node>;
|
||||
|
|
@ -100,9 +100,9 @@ private:
|
|||
public:
|
||||
using endpoint_ptr = std::shared_ptr<relation_endpoint>;
|
||||
|
||||
static void complete(const std::shared_ptr<repository_node> &node) {
|
||||
static void complete(const std::shared_ptr<repository_node> &node, const std::vector<std::unique_ptr<observer<Type>>> &observers) {
|
||||
internal::shadow_repository shadow(node->repo_);
|
||||
relation_completer completer(shadow);
|
||||
relation_completer completer(shadow, observers);
|
||||
|
||||
completer.complete_node_relations(node);
|
||||
}
|
||||
|
|
@ -131,10 +131,10 @@ public:
|
|||
void on_has_many_to_many(const char *id, CollectionType &collection, const utils::foreign_attributes &attr);
|
||||
|
||||
private:
|
||||
explicit relation_completer(internal::shadow_repository &shadow)
|
||||
: schema_(shadow)
|
||||
, log_(logger::create_logger("relation_completer")) {
|
||||
}
|
||||
explicit relation_completer(internal::shadow_repository &shadow, const std::vector<std::unique_ptr<observer<Type>>>& observers)
|
||||
: schema_(shadow)
|
||||
, log_(logger::create_logger("relation_completer"))
|
||||
, observers_(observers) {}
|
||||
|
||||
void complete_node_relations(const std::shared_ptr<repository_node> &node) {
|
||||
nodes_.push(node);
|
||||
|
|
@ -152,16 +152,19 @@ private:
|
|||
static void link_relation_endpoints(const endpoint_ptr &endpoint,
|
||||
const endpoint_ptr &other_endpoint);
|
||||
|
||||
node_ptr find_node(const std::type_index &ti) const;
|
||||
|
||||
private:
|
||||
std::stack<node_ptr> nodes_;
|
||||
internal::shadow_repository &schema_;
|
||||
logger::logger log_;
|
||||
join_columns_collector join_columns_collector_{};
|
||||
const std::vector<std::unique_ptr<observer<Type>>>& observers_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class CollectionType>
|
||||
void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
||||
void relation_completer<Type, Observers...>::on_has_many(const char *id, CollectionType &,
|
||||
const char *join_column,
|
||||
const utils::foreign_attributes &,
|
||||
std::enable_if_t<is_object_ptr<typename CollectionType::value_type>::value> * /*unused*/) {
|
||||
|
|
@ -170,12 +173,11 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
|||
using relation_value_type = many_to_many_relation<Type, value_type>;
|
||||
|
||||
// Check if the object_ptr type is already inserted in the schema (by id)
|
||||
auto result = schema_.find_node(typeid(value_type));
|
||||
if (!result) {
|
||||
auto foreign_node = find_node(typeid(value_type));
|
||||
if (!foreign_node) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
const auto foreign_node = result.value();
|
||||
// has foreign node corresponding join column (join_column)
|
||||
|
||||
if (const auto it = foreign_node->info_->find_relation_endpoint(typeid(Type)); it != foreign_node->info().endpoint_end()) {
|
||||
|
|
@ -198,8 +200,8 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
|||
log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column);
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>("id", join_column);
|
||||
});
|
||||
result = schema_.attach_node(node);
|
||||
}, {});
|
||||
const auto result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
|
|
@ -215,9 +217,9 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class CollectionType>
|
||||
void relation_completer<Type>::on_has_many(const char *id, CollectionType &, const char *join_column,
|
||||
void relation_completer<Type, Observers...>::on_has_many(const char *id, CollectionType &, const char *join_column,
|
||||
const utils::foreign_attributes &,
|
||||
std::enable_if_t<!is_object_ptr<typename CollectionType::value_type>::value>
|
||||
* /*unused*/) {
|
||||
|
|
@ -226,7 +228,7 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &, con
|
|||
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, "value");
|
||||
});
|
||||
}, {});
|
||||
const auto result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal exception
|
||||
|
|
@ -241,9 +243,9 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &, con
|
|||
link_relation_endpoints(local_endpoint, foreign_endpoint);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class CollectionType>
|
||||
void relation_completer<Type>::on_has_many_to_many(const char *id,
|
||||
void relation_completer<Type, Observers...>::on_has_many_to_many(const char *id,
|
||||
CollectionType &/*collection*/,
|
||||
const char *join_column,
|
||||
const char *inverse_join_column,
|
||||
|
|
@ -256,9 +258,9 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class CollectionType>
|
||||
void relation_completer<Type>::on_has_many_to_many(const char *id,
|
||||
void relation_completer<Type, Observers...>::on_has_many_to_many(const char *id,
|
||||
CollectionType &collection,
|
||||
const utils::foreign_attributes &attr) {
|
||||
const auto join_columns = join_columns_collector_.collect<typename CollectionType::value_type::value_type>();
|
||||
|
|
@ -270,46 +272,43 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
|||
attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class ForeignPointerType>
|
||||
void relation_completer<Type>::on_has_one(const char *id,
|
||||
void relation_completer<Type, Observers...>::on_has_one(const char *id,
|
||||
ForeignPointerType &/*obj*/,
|
||||
const utils::foreign_attributes &/*attr*/) {
|
||||
using value_type = typename ForeignPointerType::value_type;
|
||||
const auto ti = std::type_index(typeid(value_type));
|
||||
const auto result = schema_.find_node(ti);
|
||||
if (!result) {
|
||||
// Node was not found
|
||||
// Todo: Throw internal error
|
||||
auto foreign_node = find_node(typeid(value_type));
|
||||
if (!foreign_node) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
|
||||
auto local_it = nodes_.top()->info().find_relation_endpoint(typeid(value_type));
|
||||
if (local_it == nodes_.top()->info().endpoint_end()) {
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasOne, result.value());
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasOne, foreign_node);
|
||||
local_it = nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
}
|
||||
if (const auto foreign_it = result.value()->info().find_relation_endpoint(typeid(Type)); foreign_it != result.value()->info().endpoint_end()) {
|
||||
if (const auto foreign_it = foreign_node->info().find_relation_endpoint(typeid(Type)); foreign_it != foreign_node->info().endpoint_end()) {
|
||||
link_relation_endpoints(local_it->second, foreign_it->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<class ForeignPointerType>
|
||||
void relation_completer<Type>::on_belongs_to(const char *id,
|
||||
void relation_completer<Type, Observers...>::on_belongs_to(const char *id,
|
||||
ForeignPointerType & /*obj*/,
|
||||
const utils::foreign_attributes & /*attr*/) {
|
||||
using value_type = typename ForeignPointerType::value_type;
|
||||
const auto ti = std::type_index(typeid(value_type));
|
||||
auto result = schema_.find_node(ti);
|
||||
if (!result) {
|
||||
// Type was not found
|
||||
// Todo: Throw internal error
|
||||
auto foreign_node = find_node(typeid(value_type));
|
||||
if (!foreign_node) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
|
||||
// Type was found
|
||||
const auto &foreign_node = result.value();
|
||||
// Check foreign node and relation endpoint
|
||||
if (const auto it = foreign_node->info_->find_relation_endpoint(nodes_.top()->type_index()); it != foreign_node->info().endpoint_end()) {
|
||||
// Found corresponding relation endpoint in the foreign node
|
||||
|
|
@ -341,21 +340,20 @@ void relation_completer<Type>::on_belongs_to(const char *id,
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
template<typename NodeType>
|
||||
void relation_completer<Type>::attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column) {
|
||||
void relation_completer<Type, Observers...>::attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column) {
|
||||
using relation_value_type = many_to_many_relation<NodeType, Type>;
|
||||
using value_type = NodeType;
|
||||
|
||||
// Check if the object_ptr type is already inserted in the schema (by id)
|
||||
auto result = schema_.find_node(typeid(value_type));
|
||||
if (!result) {
|
||||
auto foreign_node = find_node(typeid(value_type));
|
||||
if (!foreign_node) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
|
||||
const auto foreign_node = result.value();
|
||||
result = schema_.find_node(name);
|
||||
auto result = schema_.find_node(name);
|
||||
if (result) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -364,14 +362,16 @@ void relation_completer<Type>::attach_relation_node(const std::string &name, con
|
|||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), name, std::move(creator));
|
||||
auto observers = internal::observer_list_copy_creator<Type, relation_value_type, Observers...>::copy_create(observers_);
|
||||
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), name, std::move(creator), std::move(observers));
|
||||
result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
foreign_node_completer<relation_value_type>::complete(result.value());
|
||||
foreign_node_completer<relation_value_type>::complete(result.value(), {});
|
||||
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(name, relation_type::HasMany, node);
|
||||
const auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, nodes_.top());
|
||||
|
|
@ -389,18 +389,31 @@ void relation_completer<Type>::attach_relation_node(const std::string &name, con
|
|||
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void relation_completer<Type>::register_relation_endpoints(const endpoint_ptr &endpoint,
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
void relation_completer<Type, Observers...>::register_relation_endpoints(const endpoint_ptr &endpoint,
|
||||
const endpoint_ptr &other_endpoint) {
|
||||
endpoint->node_->info_->register_relation_endpoint(other_endpoint->node_->type_index(), endpoint);
|
||||
other_endpoint->node_->info_->register_relation_endpoint(endpoint->node_->type_index(), other_endpoint);
|
||||
link_relation_endpoints(endpoint, other_endpoint);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void relation_completer<Type>::link_relation_endpoints(const endpoint_ptr &endpoint, const endpoint_ptr &other_endpoint) {
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
void relation_completer<Type, Observers...>::link_relation_endpoints(const endpoint_ptr &endpoint, const endpoint_ptr &other_endpoint) {
|
||||
endpoint->link_foreign_endpoint(other_endpoint);
|
||||
other_endpoint->link_foreign_endpoint(endpoint);
|
||||
}
|
||||
|
||||
template<typename Type, template <typename> class ... Observers>
|
||||
typename relation_completer<Type, Observers...>::node_ptr relation_completer<Type, Observers...>::find_node(const std::type_index &ti) const {
|
||||
node_ptr foreign_node;
|
||||
if (auto result = schema_.find_node(ti); result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
if (!schema_.is_node_announced(ti)) {
|
||||
return {};
|
||||
}
|
||||
return schema_.announce_node(ti);
|
||||
}
|
||||
}
|
||||
#endif //RELATION_COMPLETER_HPP
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public:
|
|||
void link_foreign_endpoint(const std::shared_ptr<relation_endpoint>& endpoint);
|
||||
|
||||
private:
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
friend class relation_completer;
|
||||
template<typename Type, template<typename> typename ...Observers>
|
||||
friend class foreign_node_completer;
|
||||
|
|
|
|||
|
|
@ -38,44 +38,55 @@ public:
|
|||
*/
|
||||
explicit repository(std::string name = "");
|
||||
|
||||
template<typename Type, typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||
return attach_type<Type, Observers...>(name, std::string{}, std::forward<Observers>(observers)...);
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers<Type>&&... observers) {
|
||||
return attach_type<Type, Observers...>(name, std::string{}, std::forward<Observers<Type>>(observers)...);
|
||||
}
|
||||
|
||||
template<typename Type, typename SuperType, typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||
template<typename Type, typename SuperType, template<typename> typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers<Type>&&... observers) {
|
||||
const auto ti = std::type_index(typeid(SuperType));
|
||||
auto result = find_node(ti);
|
||||
if (!result) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + std::string(ti.name()) + "' not found"));
|
||||
}
|
||||
|
||||
return attach_type<Type, Observers...>(name, (*result)->name(), std::forward<Observers>(observers)...);
|
||||
return attach_type<Type, Observers...>(name, (*result)->name(), std::forward<Observers<Type>>(observers)...);
|
||||
}
|
||||
|
||||
template<typename Type, typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent, Observers&&... observers) {
|
||||
return attach_type<Type, Observers...>(name, parent, std::forward<Observers>(observers)...);
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent, Observers<Type>&&... observers) {
|
||||
return attach_type<Type, Observers...>(name, parent, std::forward<Observers<Type>>(observers)...);
|
||||
}
|
||||
template<typename Type, typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach_type(const std::string &name, const std::string &parent, Observers&&... observers) {
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach_type(const std::string &name, const std::string &parent, Observers<Type>&&... observers) {
|
||||
if (const auto it = nodes_by_type_.find(typeid(Type)); it == nodes_by_type_.end() ) {
|
||||
std::vector<std::unique_ptr<observer<Type>>> obs;
|
||||
obs.reserve(sizeof...(Observers));
|
||||
(obs.push_back(std::unique_ptr<observer<Type>>(new Observers<Type>(std::forward<Observers<Type>>(observers)))), ...);
|
||||
// if the type was not found
|
||||
auto node = repository_node::make_node<Type>(*this, name, []{ return std::make_unique<Type>(); }, std::forward<Observers>(observers)...);
|
||||
std::shared_ptr<repository_node> node;
|
||||
if (is_node_announced(typeid(Type))) {
|
||||
node = pop_announce_node(typeid(Type));
|
||||
node->update_name(name);
|
||||
} else {
|
||||
node = repository_node::make_node<Type>(*this, name, []{ return std::make_unique<Type>(); }, std::move(obs));
|
||||
}
|
||||
if (auto result = attach_node(node, parent); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
foreign_node_completer<Type>::complete(node);
|
||||
relation_completer<Type>::complete(node);
|
||||
const auto info = node->template info<Type>();
|
||||
foreign_node_completer<Type, Observers...>::complete(node, info.get().observers());
|
||||
relation_completer<Type, Observers...>::complete(node, info.get().observers());
|
||||
} else if (!has_node(name)) {
|
||||
it->second->update_name(name);
|
||||
nodes_by_name_[name] = it->second;
|
||||
if (const auto i = nodes_by_name_.find(""); i != nodes_by_name_.end()) {
|
||||
nodes_by_name_.erase(i);
|
||||
}
|
||||
relation_completer<Type>::complete(it->second);
|
||||
const auto info = it->second->info<Type>();
|
||||
relation_completer<Type, Observers...>::complete(it->second, info.get().observers());
|
||||
log_.info("attach: update node name to '%s' (type: %s)", it->second->name().c_str(), it->second->type_index().name());
|
||||
} else {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + name + "' already exists"));
|
||||
|
|
@ -195,6 +206,11 @@ private:
|
|||
[[nodiscard]] std::shared_ptr<object> object_for_type(const std::type_index &ti) const;
|
||||
void remove_object_for_type(const std::type_index &ti);
|
||||
|
||||
[[nodiscard]] bool is_node_announced(const std::type_index &ti) const;
|
||||
void push_announce_node(const std::type_index &ti, const node_ptr &node);
|
||||
[[nodiscard]] node_ptr announce_node(const std::type_index &ti);
|
||||
[[nodiscard]] node_ptr pop_announce_node(const std::type_index &ti);
|
||||
|
||||
private:
|
||||
friend class internal::shadow_repository;
|
||||
friend class repository_node;
|
||||
|
|
@ -209,9 +225,11 @@ private:
|
|||
t_type_index_node_map nodes_by_type_;
|
||||
logger::logger log_;
|
||||
|
||||
std::unordered_map<std::type_index, std::shared_ptr<repository_node>> announced_node_;
|
||||
std::unordered_map<std::type_index, attribute*> missing_references_;
|
||||
std::unordered_map<std::string, std::type_index> expected_relation_nodes_;
|
||||
std::unordered_map<std::type_index, std::shared_ptr<object>> object_by_type_;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "matador/object/object_generator.hpp"
|
||||
#include "matador/object/object_info.hpp"
|
||||
#include "matador/object/internal/observer_list_creator.hpp"
|
||||
|
||||
#include "matador/utils/error.hpp"
|
||||
#include "matador/utils/result.hpp"
|
||||
|
|
@ -20,22 +21,11 @@ public:
|
|||
template< typename Type>
|
||||
using creator_func = std::function<std::unique_ptr<Type>()>;
|
||||
|
||||
template < typename Type, typename... Observers >
|
||||
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name, creator_func<Type> creator, Observers&&... observers) {
|
||||
const std::type_index ti(typeid(Type));
|
||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, ti));
|
||||
|
||||
auto obj = object_generator::generate<Type>(creator(), repo, name);
|
||||
auto info = std::make_unique<object_info<Type>>(
|
||||
node,
|
||||
std::move(obj),
|
||||
std::forward<creator_func<Type>>(creator)
|
||||
);
|
||||
(info->register_observer(observer_ptr<Type>(std::unique_ptr<Observers>(new Observers(std::forward<Observers>(observers))))), ...);
|
||||
node->info_ = std::move(info);
|
||||
|
||||
return node;
|
||||
}
|
||||
template < typename Type, template<typename> typename... Observers >
|
||||
static std::shared_ptr<repository_node> make_node(repository& repo,
|
||||
const std::string& name,
|
||||
creator_func<Type> creator,
|
||||
std::vector<std::unique_ptr<observer<Type>>>&& observers);
|
||||
|
||||
static std::shared_ptr<repository_node> make_null_node(repository& repo);
|
||||
|
||||
|
|
@ -74,11 +64,9 @@ private:
|
|||
|
||||
void unlink();
|
||||
|
||||
static utils::result<node_ptr, utils::error> make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti);
|
||||
|
||||
private:
|
||||
friend class repository;
|
||||
template<typename Type>
|
||||
template<typename Type, template<typename> typename... Observers>
|
||||
friend class relation_completer;
|
||||
template < typename NodeType, template<typename> typename ...Observers >
|
||||
friend class foreign_node_completer;
|
||||
|
|
@ -98,5 +86,24 @@ private:
|
|||
size_t depth_{0};
|
||||
};
|
||||
|
||||
template<typename Type, template <typename> class ... Observers>
|
||||
std::shared_ptr<repository_node> repository_node::make_node(repository &repo, const std::string &name,
|
||||
creator_func<Type> creator, std::vector<std::unique_ptr<observer<Type>>> &&observers) {
|
||||
const std::type_index ti(typeid(Type));
|
||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, ti));
|
||||
|
||||
internal::observer_list_creator<Type, Observers...>::create_missing(observers);
|
||||
|
||||
auto obj = object_generator::generate<Type>(creator(), repo, name);
|
||||
auto info = std::make_unique<object_info<Type>>(
|
||||
node,
|
||||
std::move(obj),
|
||||
std::move(observers),
|
||||
std::forward<creator_func<Type>>(creator)
|
||||
);
|
||||
node->info_ = std::move(info);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
#endif //SCHEMA_NODE_HPP
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/generator.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
|
|
@ -15,7 +16,6 @@
|
|||
#include "matador/sql/statement_cache.hpp"
|
||||
|
||||
#include "matador/object/object_ptr.hpp"
|
||||
#include "matador/object/repository.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -71,35 +71,20 @@ public:
|
|||
|
||||
}
|
||||
template<class Pointer>
|
||||
void on_has_one(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
||||
|
||||
}
|
||||
void on_has_one(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {}
|
||||
template<class ContainerType>
|
||||
void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) {
|
||||
}
|
||||
void on_has_many(const char * /*id*/, ContainerType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
||||
template<class ContainerType>
|
||||
void on_has_many_to_many(const char *id, ContainerType &/*cont*/, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr) {
|
||||
|
||||
}
|
||||
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
||||
template<class ContainerType>
|
||||
void on_has_many_to_many(const char *id, ContainerType &/*cont*/, const utils::foreign_attributes &attr) {
|
||||
|
||||
}
|
||||
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const utils::foreign_attributes &/*attr*/) {}
|
||||
|
||||
private:
|
||||
const std::unordered_map<std::string, sql::statement> &statements_per_column_;
|
||||
};
|
||||
class session final : public sql::executor {
|
||||
public:
|
||||
explicit session(session_context &&ctx);
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &table_name) const;
|
||||
template<typename Type, typename SuperType>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &table_name) const;
|
||||
|
||||
utils::result<void, utils::error> create_schema() const;
|
||||
utils::result<void, utils::error> drop_schema() const;
|
||||
session(session_context &&ctx, const query::schema &scm);
|
||||
|
||||
/**
|
||||
* Insert the given object into the session.
|
||||
|
|
@ -145,35 +130,24 @@ private:
|
|||
friend class query_select;
|
||||
|
||||
static query::fetchable_query build_select_query(entity_query_data &&data);
|
||||
static sql::query_context build_add_constraint_context(const std::string& table_name, const class object::restriction& cons, const sql::connection_ptr &conn) ;
|
||||
|
||||
private:
|
||||
mutable sql::statement_cache cache_;
|
||||
const sql::dialect &dialect_;
|
||||
|
||||
std::unique_ptr<object::repository> schema_;
|
||||
const query::schema& schema_;
|
||||
mutable std::unordered_map<std::string, std::vector<object::attribute>> prototypes_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> session::attach(const std::string &table_name) const {
|
||||
return schema_->attach<Type>(table_name);
|
||||
}
|
||||
|
||||
template<typename Type, typename SuperType>
|
||||
utils::result<void, utils::error> session::attach( const std::string& table_name ) const {
|
||||
return schema_->attach<Type, SuperType>(table_name);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj) {
|
||||
auto info = schema_->info<Type>();
|
||||
auto info = schema_.repo().info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
|
||||
auto res = query::query::insert()
|
||||
.into(info->get().name(), query::generator::columns<Type>(*schema_))
|
||||
.into(info->get().name(), query::generator::columns<Type>(schema_))
|
||||
.values(query::generator::placeholders<Type>())
|
||||
.prepare(*this);
|
||||
if (!res) {
|
||||
|
|
@ -240,14 +214,14 @@ private:
|
|||
|
||||
template<typename Type>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::update( const object::object_ptr<Type>& obj ) {
|
||||
auto info = schema_->info<Type>();
|
||||
auto info = schema_.repo().info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
using namespace matador::utils;
|
||||
using namespace matador::query;
|
||||
|
||||
const auto col = column(info.value().get().primary_key_attribute()->name());
|
||||
const auto col = table_column(info.value().get().primary_key_attribute()->name());
|
||||
auto res = matador::query::query::update(info->get().name())
|
||||
.set(generator::column_value_pairs<Type>())
|
||||
.where(col == _)
|
||||
|
|
@ -266,14 +240,14 @@ utils::result<object::object_ptr<Type>, utils::error> session::update( const obj
|
|||
|
||||
template<typename Type>
|
||||
utils::result<void, utils::error> session::remove( const object::object_ptr<Type>& obj ) {
|
||||
auto info = schema_->info<Type>();
|
||||
auto info = schema_.repo().info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
using namespace matador::utils;
|
||||
using namespace matador::query;
|
||||
|
||||
const auto col = column(info.value().get().primary_key_attribute()->name());
|
||||
const auto col = table_column(info.value().get().primary_key_attribute()->name());
|
||||
auto res = matador::query::query::remove()
|
||||
.from( info->get().name() )
|
||||
.where(col == _)
|
||||
|
|
@ -291,22 +265,24 @@ utils::result<void, utils::error> session::remove( const object::object_ptr<Type
|
|||
|
||||
template<typename Type, typename PrimaryKeyType>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::find(const PrimaryKeyType& pk) {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
const auto it = schema_.find(typeid(Type));
|
||||
if (it == schema_.end()) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
if (!info.value().get().has_primary_key()) {
|
||||
const auto& info = it->second.node().info();
|
||||
// if (!info) {
|
||||
// return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
// }
|
||||
if (!info.has_primary_key()) {
|
||||
return utils::failure(make_error(error_code::NoPrimaryKey, "Type hasn't primary key."));
|
||||
}
|
||||
|
||||
const auto& type_info = info.value().get();
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
const query::column col(std::make_shared<query::table>(type_info.name()), type_info.primary_key_attribute()->name());
|
||||
session_query_builder eqb(schema_, *this);
|
||||
const query::table_column c(&it->second.table(),info.primary_key_attribute()->name());
|
||||
using namespace matador::query;
|
||||
auto data = eqb.build<Type>(col == utils::_);
|
||||
auto data = eqb.build<Type>(c == utils::_);
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + type_info.name() + "."));
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info.name() + "."));
|
||||
}
|
||||
|
||||
auto res = build_select_query(data.release()).prepare(*this);
|
||||
|
|
@ -316,19 +292,19 @@ utils::result<object::object_ptr<Type>, utils::error> session::find(const Primar
|
|||
}
|
||||
auto stmt_result = res->bind(0, const_cast<PrimaryKeyType&>(pk)).template fetch_one<Type>();
|
||||
if (stmt_result && !stmt_result.value()) {
|
||||
return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + type_info.name() + " with primary key " + std::to_string(pk) + "."));
|
||||
return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info.name() + " with primary key " + std::to_string(pk) + "."));
|
||||
}
|
||||
return utils::ok(object::object_ptr<Type>{ stmt_result->release() });
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
utils::result<sql::query_result<Type>, utils::error> session::find(query::criteria_ptr clause) {
|
||||
auto info = schema_->info<Type>();
|
||||
auto info = schema_.repo().info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
session_query_builder eqb(schema_, *this);
|
||||
auto data = eqb.build<Type>(std::move(clause));
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + "."));
|
||||
|
|
@ -344,7 +320,7 @@ utils::result<sql::query_result<Type>, utils::error> session::find(query::criter
|
|||
|
||||
template<typename Type>
|
||||
utils::result<void, utils::error> session::drop_table() {
|
||||
auto info = schema_->info<Type>();
|
||||
auto info = schema_.repo().info<Type>();
|
||||
if (info) {
|
||||
return drop_table(info->get().name());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
namespace matador::orm {
|
||||
|
||||
struct entity_query_data {
|
||||
std::shared_ptr<query::table> root_table;
|
||||
const query::table* root_table{nullptr};
|
||||
std::string pk_column_name{};
|
||||
std::vector<query::column> columns{};
|
||||
std::vector<query::table_column> columns{};
|
||||
std::unordered_map<std::string, sql::statement> lazy_loading_statements{};
|
||||
std::vector<query::join_data> joins{};
|
||||
query::criteria_ptr where_clause{};
|
||||
|
|
@ -34,7 +34,7 @@ struct entity_query_data {
|
|||
|
||||
class criteria_transformer final : public query::criteria_visitor {
|
||||
public:
|
||||
criteria_transformer(const query::schema &repo, const std::unordered_map<std::string, std::shared_ptr<query::table>>& tables_by_name);
|
||||
criteria_transformer(const query::schema &repo, const std::unordered_map<std::string, query::table>& tables_by_name);
|
||||
void visit( const query::between_criteria& node ) override;
|
||||
void visit( const query::binary_criteria& node ) override;
|
||||
void visit( const query::binary_column_criteria& node ) override;
|
||||
|
|
@ -49,7 +49,7 @@ private:
|
|||
|
||||
private:
|
||||
const query::schema &repo_;
|
||||
const std::unordered_map<std::string, std::shared_ptr<query::table>>& tables_by_name_;
|
||||
const std::unordered_map<std::string, query::table>& tables_by_name_;
|
||||
};
|
||||
|
||||
class session_query_builder final {
|
||||
|
|
@ -60,15 +60,16 @@ public:
|
|||
|
||||
template<class EntityType>
|
||||
utils::result<entity_query_data, query_build_error> build(query::criteria_ptr clause = {}) {
|
||||
const auto info = schema_.repo().info<EntityType>();
|
||||
if (!info) {
|
||||
const auto it = schema_.find(typeid(EntityType));
|
||||
if (it == schema_.end()) {
|
||||
return utils::failure(query_build_error::UnknownType);
|
||||
}
|
||||
table_info_stack_.push({info.value(), std::make_shared<query::table>(info.value().get().name(), build_alias('t', ++table_index))});
|
||||
entity_query_data_ = { table_info_stack_.top().table };
|
||||
processed_tables_.insert({info->get().name(), entity_query_data_.root_table});
|
||||
table_info_stack_.push({it->second.node().info(), it->second.table().as(build_alias('t', ++table_index))});
|
||||
entity_query_data_ = { &table_info_stack_.top().table };
|
||||
processed_tables_.insert({it->second.name(), *entity_query_data_.root_table});
|
||||
try {
|
||||
access::process(*this, info->get().prototype());
|
||||
EntityType obj;
|
||||
access::process(*this, obj);
|
||||
|
||||
if (clause) {
|
||||
criteria_transformer transformer{schema_, processed_tables_};
|
||||
|
|
@ -101,45 +102,77 @@ public:
|
|||
}
|
||||
|
||||
template<class Pointer>
|
||||
void on_belongs_to(const char *id, Pointer &obj, const utils::foreign_attributes &attr)
|
||||
{
|
||||
void on_belongs_to(const char *id, Pointer &obj, const utils::foreign_attributes &attr) {
|
||||
on_foreign_object(id, obj, attr);
|
||||
}
|
||||
|
||||
template<class Pointer>
|
||||
void on_has_one(const char *id, Pointer &obj, const utils::foreign_attributes &attr)
|
||||
{
|
||||
void on_has_one(const char *id, Pointer &obj, const utils::foreign_attributes &attr) {
|
||||
on_foreign_object(id, obj, attr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct NoopDeleter {
|
||||
void operator()(const T*) const {}
|
||||
};
|
||||
|
||||
template<class ContainerType>
|
||||
void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) {
|
||||
if (attr.fetch() == utils::fetch_type::Eager) {
|
||||
const auto result = schema_.repo().basic_info(typeid(typename ContainerType::value_type::value_type));
|
||||
if (!result) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
|
||||
const auto &info = result.value().get();
|
||||
auto next = processed_tables_.find(info.name());
|
||||
if (next != processed_tables_.end()) {
|
||||
return;
|
||||
}
|
||||
table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||
typename ContainerType::value_type::value_type obj;
|
||||
access::process(*this , obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
if (!info.has_primary_key()) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
append_join(
|
||||
query::column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
||||
query::column{next->second.get(), join_column}
|
||||
);
|
||||
if (attr.fetch() != utils::fetch_type::Eager) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto it = schema_.find(typeid(typename ContainerType::value_type::value_type));
|
||||
if (it == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
|
||||
auto next = processed_tables_.find(it->second.name());
|
||||
if (next != processed_tables_.end()) {
|
||||
// node already processed
|
||||
return;
|
||||
}
|
||||
|
||||
table_info_stack_.push({it->second.node().info(), it->second.table().as(build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({it->second.name(), table_info_stack_.top().table}).first;
|
||||
typename ContainerType::value_type::value_type obj;
|
||||
access::process(*this , obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
if (!it->second.node().info().has_primary_key()) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
append_join(
|
||||
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||
query::table_column{&next->second, join_column}
|
||||
);
|
||||
|
||||
|
||||
// const auto result = schema_.repo().basic_info(typeid(typename ContainerType::value_type::value_type));
|
||||
// if (!result) {
|
||||
// throw query_builder_exception{query_build_error::UnknownType};
|
||||
// }
|
||||
//
|
||||
// const auto &info = result.value().get();
|
||||
// auto next = processed_tables_.find(info.name());
|
||||
// if (next != processed_tables_.end()) {
|
||||
// return;
|
||||
// }
|
||||
// table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
|
||||
// next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||
// typename ContainerType::value_type::value_type obj;
|
||||
// access::process(*this , obj);
|
||||
// table_info_stack_.pop();
|
||||
//
|
||||
// if (!info.has_primary_key()) {
|
||||
// throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
// }
|
||||
//
|
||||
// append_join(
|
||||
// query::column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
||||
// query::column{next->second.get(), join_column}
|
||||
// );
|
||||
}
|
||||
|
||||
template<class ContainerType>
|
||||
|
|
@ -147,38 +180,42 @@ public:
|
|||
if (attr.fetch() != utils::fetch_type::Eager) {
|
||||
return;
|
||||
}
|
||||
const auto result = schema_.repo().basic_info(typeid(typename ContainerType::value_type::value_type));
|
||||
if (!result) {
|
||||
const auto result = schema_.find(typeid(typename ContainerType::value_type::value_type));
|
||||
if (result == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
|
||||
const auto &info = result.value().get();
|
||||
auto next = processed_tables_.find(info.name());
|
||||
auto next = processed_tables_.find(result->second.name());
|
||||
if (next != processed_tables_.end()) {
|
||||
// attribute was already processed
|
||||
return;
|
||||
}
|
||||
|
||||
auto relation = processed_tables_.find(id);
|
||||
if (relation == processed_tables_.end()) {
|
||||
relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first;
|
||||
const auto it = schema_.find(id);
|
||||
if (it == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
relation = processed_tables_.emplace(id, it->second.table().as(build_alias('t', ++table_index))).first;
|
||||
}
|
||||
|
||||
table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||
table_info_stack_.push({result->second.node().info(), result->second.table().as(build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({result->second.name(), table_info_stack_.top().table}).first;
|
||||
typename ContainerType::value_type::value_type obj;
|
||||
access::process(*this , obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
if (!info.has_primary_key()) {
|
||||
if (!result->second.node().info().has_primary_key()) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
append_join(
|
||||
query::column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
||||
query::column{relation->second.get(), join_column}
|
||||
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||
query::table_column{&relation->second, join_column}
|
||||
);
|
||||
append_join(
|
||||
query::column{relation->second.get(), inverse_join_column},
|
||||
query::column{next->second.get(), info.primary_key_attribute()->name()}
|
||||
query::table_column{&relation->second, inverse_join_column},
|
||||
query::table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -187,40 +224,45 @@ public:
|
|||
if (attr.fetch() != utils::fetch_type::Eager) {
|
||||
return;
|
||||
}
|
||||
const auto result = schema_.repo().basic_info(typeid(typename ContainerType::value_type::value_type));
|
||||
if (!result) {
|
||||
const auto result = schema_.find(typeid(typename ContainerType::value_type::value_type));
|
||||
if (result == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
|
||||
const auto &info = result.value().get();
|
||||
auto next = processed_tables_.find(info.name());
|
||||
auto next = processed_tables_.find(result->second.name());
|
||||
if (next != processed_tables_.end()) {
|
||||
// attribute was already processed
|
||||
return;
|
||||
}
|
||||
|
||||
auto relation = processed_tables_.find(id);
|
||||
if (relation == processed_tables_.end()) {
|
||||
relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first;
|
||||
const auto it = schema_.find(id);
|
||||
if (it == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
const auto t = it->second.table().as(build_alias('t', ++table_index));
|
||||
relation = processed_tables_.insert({id, t}).first;
|
||||
}
|
||||
table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||
table_info_stack_.push({result->second.node().info(), result->second.table().as(build_alias('t', ++table_index))});
|
||||
next = processed_tables_.insert({result->second.name(), table_info_stack_.top().table}).first;
|
||||
typename ContainerType::value_type::value_type obj;
|
||||
access::process(*this , obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
if (!info.has_primary_key()) {
|
||||
if (!result->second.node().info().has_primary_key()) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
const auto join_columns = join_columns_collector_.collect<typename ContainerType::value_type::value_type>();
|
||||
|
||||
append_join(
|
||||
query::column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
||||
query::column{relation->second.get(), join_columns.inverse_join_column}
|
||||
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||
query::table_column{&relation->second, join_columns.inverse_join_column}
|
||||
);
|
||||
append_join(
|
||||
query::column{relation->second.get(), join_columns.join_column},
|
||||
query::column{next->second.get(), info.primary_key_attribute()->name()}
|
||||
query::table_column{&relation->second, join_columns.join_column},
|
||||
query::table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -230,16 +272,18 @@ private:
|
|||
void push(const std::string &column_name);
|
||||
static std::string build_alias(char prefix, unsigned int count);
|
||||
[[nodiscard]] bool is_root_entity() const;
|
||||
void append_join(const query::column &left, const query::column &right);
|
||||
void append_join(const query::table_column &left, const query::table_column &right);
|
||||
|
||||
private:
|
||||
struct table_info {
|
||||
std::reference_wrapper<const object::basic_object_info> info;
|
||||
std::shared_ptr<query::table> table;
|
||||
const object::basic_object_info &info;
|
||||
query::table table;
|
||||
// std::reference_wrapper<const object::basic_object_info> info;
|
||||
// std::shared_ptr<query::table> table;
|
||||
};
|
||||
|
||||
std::stack<table_info> table_info_stack_{};
|
||||
std::unordered_map<std::string, std::shared_ptr<query::table>> processed_tables_{};
|
||||
std::unordered_map<std::string, query::table> processed_tables_{};
|
||||
const query::schema &schema_;
|
||||
entity_query_data entity_query_data_{};
|
||||
unsigned int column_index{0};
|
||||
|
|
@ -250,30 +294,31 @@ private:
|
|||
|
||||
template<class Pointer>
|
||||
void session_query_builder::on_foreign_object(const char *id, Pointer &, const utils::foreign_attributes &attr) {
|
||||
const auto info = schema_.repo().info<typename Pointer::value_type>();
|
||||
if (!info) {
|
||||
const auto it = schema_.find(typeid(typename Pointer::value_type));
|
||||
if (it == schema_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
if (!info->get().has_primary_key()) {
|
||||
if (!it->second.node().info().has_primary_key()) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
const auto foreign_table = std::make_shared<query::table>(info->get().name(), build_alias('t', ++table_index));
|
||||
const auto& info = it->second.node().info();
|
||||
auto foreign_table = it->second.table().as(build_alias('t', ++table_index));
|
||||
if (attr.fetch() == utils::fetch_type::Eager) {
|
||||
|
||||
auto next = processed_tables_.find(info->get().name());
|
||||
auto next = processed_tables_.find(info.name());
|
||||
if (next != processed_tables_.end()) {
|
||||
return;
|
||||
}
|
||||
table_info_stack_.push({info.value(), foreign_table});
|
||||
next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first;
|
||||
table_info_stack_.push({info, std::move(foreign_table)});
|
||||
next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||
typename Pointer::value_type obj;
|
||||
access::process(*this, obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
append_join(
|
||||
query::column{table_info_stack_.top().table.get(), id},
|
||||
query::column{next->second.get(), info->get().primary_key_attribute()->name()}
|
||||
query::table_column{&table_info_stack_.top().table, id},
|
||||
query::table_column{&next->second, info.primary_key_attribute()->name()}
|
||||
);
|
||||
} else {
|
||||
push(id);
|
||||
|
|
@ -281,8 +326,8 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u
|
|||
using namespace matador::query;
|
||||
// create select query
|
||||
auto result = matador::query::query::select(generator::columns<typename Pointer::value_type>(schema_, generator::column_generator_options::ForceLazy))
|
||||
.from(*foreign_table)
|
||||
.where(column(foreign_table.get(), info->get().primary_key_attribute()->name(), "") == _)
|
||||
.from(foreign_table)
|
||||
.where(table_column(&foreign_table, info.primary_key_attribute()->name(), "") == _)
|
||||
.prepare(executor_);
|
||||
if (!result) {
|
||||
throw query_builder_exception(query_build_error::QueryError, result.release_error());
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef MATADOR_BUILDER_HPP
|
||||
#define MATADOR_BUILDER_HPP
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
|
|
@ -65,28 +65,28 @@ public:
|
|||
explicit column_builder(std::string column_name, utils::basic_type type, size_t size = 0);
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator column() const; // NOLINT(*-explicit-constructor)
|
||||
operator table_column() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
column_builder& not_null();
|
||||
column_builder& primary_key();
|
||||
column_builder& unique();
|
||||
|
||||
private:
|
||||
std::string column_name_;
|
||||
utils::basic_type type_{};
|
||||
utils::constraints constraints_{};
|
||||
utils::constraints constraints_{utils::constraints::NotNull};
|
||||
size_t size_{0};
|
||||
};
|
||||
|
||||
class table_builder {
|
||||
public:
|
||||
explicit table_builder(std::string name);
|
||||
|
||||
table_builder& as(std::string table_alias);
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator table() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
private:
|
||||
std::string table_name;
|
||||
std::string alias;
|
||||
};
|
||||
|
||||
class constraint_builder {
|
||||
|
|
@ -97,19 +97,19 @@ public:
|
|||
constraint_builder& references(std::string table, std::string column);
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator class constraint() const; // NOLINT(*-explicit-constructor)
|
||||
operator table_constraint() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
private:
|
||||
std::string constraint_name;
|
||||
std::string pk_column_name;
|
||||
std::string fk_column_name;
|
||||
std::string table_name;
|
||||
std::string column_name;
|
||||
std::string constraint_name_;
|
||||
std::string column_name_;
|
||||
std::string ref_table_name_;
|
||||
std::string ref_column_name_;
|
||||
utils::constraints type_{};
|
||||
};
|
||||
|
||||
constraint_builder constraint(std::string name);
|
||||
// table_builder table(std::string name);
|
||||
// column_builder column(std::string name, utils::basic_type type, size_t size = 0);
|
||||
column_builder column(std::string name, utils::basic_type type, size_t size = 0);
|
||||
|
||||
}
|
||||
#endif //MATADOR_BUILDER_HPP
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef QUERY_COLUMN_HPP
|
||||
#define QUERY_COLUMN_HPP
|
||||
|
||||
#include "matador/sql/sql_functions.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
class table;
|
||||
|
||||
// ReSharper disable CppNonExplicitConvertingConstructor
|
||||
class column {
|
||||
public:
|
||||
column(const char *name); // NOLINT(*-explicit-constructor)
|
||||
column(std::string name); // NOLINT(*-explicit-constructor)
|
||||
column(std::string name, std::string alias);
|
||||
column(sql::sql_function_t func, std::string name);
|
||||
column(const class table* tab, std::string name);
|
||||
column(const class table* tab, std::string name, std::string alias);
|
||||
column(const class table* tab, std::string name, utils::basic_type type, const utils::field_attributes& attributes);
|
||||
|
||||
[[nodiscard]] bool equals(const column &x) const;
|
||||
|
||||
column as(std::string a);
|
||||
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
[[nodiscard]] const std::string& alias() const;
|
||||
[[nodiscard]] utils::basic_type type() const;
|
||||
[[nodiscard]] utils::field_attributes attributes() const;
|
||||
|
||||
[[nodiscard]] bool is_function() const;
|
||||
[[nodiscard]] bool is_nullable() const;
|
||||
[[nodiscard]] sql::sql_function_t function() const;
|
||||
[[nodiscard]] bool has_alias() const;
|
||||
|
||||
[[nodiscard]] const class table* table() const;
|
||||
void table(const query::table* t);
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator const std::string&() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
private:
|
||||
static query::table* default_table();
|
||||
|
||||
private:
|
||||
friend class table;
|
||||
|
||||
const query::table* table_{nullptr};
|
||||
std::string name_;
|
||||
std::string alias_;
|
||||
utils::basic_type type_{utils::basic_type::Unknown};
|
||||
utils::field_attributes attributes_{};
|
||||
|
||||
sql::sql_function_t function_{sql::sql_function_t::None};
|
||||
};
|
||||
|
||||
column operator ""_col(const char *name, size_t len);
|
||||
|
||||
}
|
||||
#endif //QUERY_COLUMN_HPP
|
||||
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
#include "matador/query/criteria/abstract_criteria.hpp"
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
class abstract_column_criteria : public abstract_criteria {
|
||||
public:
|
||||
abstract_column_criteria() = delete;
|
||||
explicit abstract_column_criteria(column col);
|
||||
explicit abstract_column_criteria(const table_column& col);
|
||||
|
||||
[[nodiscard]] const column& col() const;
|
||||
[[nodiscard]] const table_column& col() const;
|
||||
|
||||
protected:
|
||||
column column_;
|
||||
table_column column_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@
|
|||
#include "matador/query/criteria/abstract_column_criteria.hpp"
|
||||
#include "matador/query/criteria/criteria_utils.hpp"
|
||||
|
||||
#include "matador/utils/value.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
class between_criteria final : public abstract_column_criteria {
|
||||
public:
|
||||
between_criteria() = delete;
|
||||
between_criteria(column col, int64_t min, int64_t max);
|
||||
between_criteria(column col, utils::placeholder min, utils::placeholder max);
|
||||
between_criteria(const table_column& col, int64_t min, int64_t max);
|
||||
between_criteria(const table_column& col, utils::placeholder min, utils::placeholder max);
|
||||
|
||||
void accept(criteria_visitor& visitor) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "matador/query/criteria/abstract_column_criteria.hpp"
|
||||
#include "matador/query/criteria/criteria_utils.hpp"
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
enum class binary_operator {
|
||||
|
|
@ -19,7 +19,7 @@ enum class binary_operator {
|
|||
class binary_criteria final : public abstract_column_criteria {
|
||||
public:
|
||||
binary_criteria() = delete;
|
||||
binary_criteria(column col, binary_operator operand, criteria_value value);
|
||||
binary_criteria(const table_column& col, binary_operator operand, criteria_value value);
|
||||
|
||||
void accept( criteria_visitor& visitor ) const override;
|
||||
|
||||
|
|
@ -34,18 +34,18 @@ private:
|
|||
class binary_column_criteria final : public abstract_criteria {
|
||||
public:
|
||||
binary_column_criteria() = delete;
|
||||
binary_column_criteria(column left_column, binary_operator operand, column right_column);
|
||||
binary_column_criteria(const table_column& left_column, binary_operator operand, const table_column& right_column);
|
||||
|
||||
void accept(criteria_visitor& visitor) const override;
|
||||
|
||||
[[nodiscard]] const column& left_column() const;
|
||||
[[nodiscard]] const table_column& left_column() const;
|
||||
[[nodiscard]] binary_operator operand() const;
|
||||
[[nodiscard]] const column& right_column() const;
|
||||
[[nodiscard]] const table_column& right_column() const;
|
||||
|
||||
private:
|
||||
column left_column_;
|
||||
table_column left_column_;
|
||||
binary_operator operator_{};
|
||||
column right_column_;
|
||||
table_column right_column_;
|
||||
};
|
||||
}
|
||||
#endif //CRITERIA_BINARY_CRITERIA_NODE_HPP
|
||||
|
|
@ -4,10 +4,12 @@
|
|||
#include "matador/query/criteria/abstract_column_criteria.hpp"
|
||||
#include "matador/query/criteria/criteria_utils.hpp"
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table.hpp"
|
||||
#include "matador/sql/query_context.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
class table_column;
|
||||
|
||||
enum class collection_operator {
|
||||
In,
|
||||
Out
|
||||
|
|
@ -36,8 +38,8 @@ public:
|
|||
* @param operand_ Operator to use
|
||||
* @param values List of values
|
||||
*/
|
||||
collection_criteria(column col, collection_operator operand_, std::vector<criteria_value> values);
|
||||
collection_criteria(column col, collection_operator operand_, std::initializer_list<criteria_value> values);
|
||||
collection_criteria(const table_column& col, collection_operator operand_, std::vector<criteria_value> values);
|
||||
collection_criteria(const table_column& col, collection_operator operand_, std::initializer_list<criteria_value> values);
|
||||
|
||||
void accept(criteria_visitor& visitor) const override;
|
||||
|
||||
|
|
@ -52,7 +54,7 @@ private:
|
|||
class collection_query_criteria final : public abstract_column_criteria {
|
||||
public:
|
||||
collection_query_criteria() = delete;
|
||||
collection_query_criteria(column col, collection_operator operand_, sql::query_context ctx);
|
||||
collection_query_criteria(const table_column& col, collection_operator operand_, sql::query_context ctx);
|
||||
|
||||
void accept(criteria_visitor& visitor) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,51 +11,51 @@ namespace matador::sql {
|
|||
struct query_context;
|
||||
}
|
||||
namespace matador::query {
|
||||
class column;
|
||||
class table_column;
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator==(const column &col, Type val) {
|
||||
criteria_ptr operator==(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, utils::value(val));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator!=(const column &col, Type val) {
|
||||
criteria_ptr operator!=(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, utils::value(val));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator>(const column &col, Type val) {
|
||||
criteria_ptr operator>(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN, utils::value(val));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator>=(const column &col, Type val) {
|
||||
criteria_ptr operator>=(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN_OR_EQUAL, utils::value(val));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator<(const column &col, Type val) {
|
||||
criteria_ptr operator<(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN, utils::value(val));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
criteria_ptr operator<=(const column &col, Type val) {
|
||||
criteria_ptr operator<=(const table_column &col, Type val) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN_OR_EQUAL, utils::value(val));
|
||||
}
|
||||
|
||||
criteria_ptr operator==(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator!=(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator>(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator>=(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator<(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator<=(const column &col_left, const column &col_right);
|
||||
criteria_ptr operator==(const table_column &col_left, const table_column &col_right);
|
||||
criteria_ptr operator!=(const table_column &col_left, const table_column &col_right);
|
||||
criteria_ptr operator>(const table_column &col_left, const table_column &col_right);
|
||||
criteria_ptr operator>=(const table_column &col_left, const table_column &col_right);
|
||||
criteria_ptr operator<(const table_column &col_left, const table_column &col_right);
|
||||
criteria_ptr operator<=(const table_column &col_left, const table_column &col_right);
|
||||
|
||||
criteria_ptr operator==(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator!=(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator>(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator>=(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator<(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator<=(const column &col, utils::placeholder p);
|
||||
criteria_ptr operator==(const table_column &col, utils::placeholder p);
|
||||
criteria_ptr operator!=(const table_column &col, utils::placeholder p);
|
||||
criteria_ptr operator>(const table_column &col, utils::placeholder p);
|
||||
criteria_ptr operator>=(const table_column &col, utils::placeholder p);
|
||||
criteria_ptr operator<(const table_column &col, utils::placeholder p);
|
||||
criteria_ptr operator<=(const table_column &col, utils::placeholder p);
|
||||
|
||||
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right);
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ criteria_ptr operator||(criteria_ptr left, criteria_ptr right);
|
|||
criteria_ptr operator!(criteria_ptr clause);
|
||||
|
||||
template < class Type >
|
||||
criteria_ptr in(const column &col, std::initializer_list<Type> args) {
|
||||
criteria_ptr in(const table_column &col, std::initializer_list<Type> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(utils::value{std::move(arg)});
|
||||
|
|
@ -73,12 +73,12 @@ criteria_ptr in(const column &col, std::initializer_list<Type> args) {
|
|||
}
|
||||
|
||||
template <>
|
||||
criteria_ptr in(const column &col, std::initializer_list<utils::placeholder> args);
|
||||
criteria_ptr in(const table_column &col, std::initializer_list<utils::placeholder> args);
|
||||
|
||||
criteria_ptr in(const column &col, sql::query_context &&ctx);
|
||||
criteria_ptr in(const table_column &col, sql::query_context &&ctx);
|
||||
|
||||
template < class Type >
|
||||
criteria_ptr out(const column &col, std::initializer_list<Type> args) {
|
||||
criteria_ptr out(const table_column &col, std::initializer_list<Type> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(utils::value{std::move(arg)});
|
||||
|
|
@ -87,14 +87,14 @@ criteria_ptr out(const column &col, std::initializer_list<Type> args) {
|
|||
}
|
||||
|
||||
template <>
|
||||
criteria_ptr out(const column &col, std::initializer_list<utils::placeholder> args);
|
||||
criteria_ptr out(const table_column &col, std::initializer_list<utils::placeholder> args);
|
||||
|
||||
criteria_ptr out(const column &col, sql::query_context &&ctx);
|
||||
criteria_ptr out(const table_column &col, sql::query_context &&ctx);
|
||||
|
||||
criteria_ptr between(const column &col, int64_t min, int64_t max);
|
||||
criteria_ptr between(const column &col, utils::placeholder min, utils::placeholder max);
|
||||
criteria_ptr between(const table_column &col, int64_t min, int64_t max);
|
||||
criteria_ptr between(const table_column &col, utils::placeholder min, utils::placeholder max);
|
||||
|
||||
criteria_ptr like(const column &col, const std::string &pattern);
|
||||
criteria_ptr like(const table_column &col, const std::string &pattern);
|
||||
|
||||
}
|
||||
#endif //CRITERIA_CRITERIA_OPERATORS_HPP
|
||||
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
#include "matador/query/criteria/abstract_column_criteria.hpp"
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
class table_column;
|
||||
|
||||
class like_criteria final : public abstract_column_criteria {
|
||||
public:
|
||||
like_criteria() = delete;
|
||||
like_criteria(column col, std::string pattern);
|
||||
like_criteria(const table_column& col, std::string pattern);
|
||||
|
||||
void accept(criteria_visitor &visitor) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,20 +45,18 @@ constexpr auto default_column_generator_options = column_generator_options::Forc
|
|||
|
||||
class column_generator {
|
||||
public:
|
||||
explicit column_generator(const std::string &table_name = "",
|
||||
column_generator_options options = default_column_generator_options);
|
||||
explicit column_generator(const schema &repo,
|
||||
const std::string &table_name = "",
|
||||
column_generator_options options = default_column_generator_options);
|
||||
|
||||
template< class Type >
|
||||
std::vector<column> generate() {
|
||||
std::vector<table_column> generate() {
|
||||
Type obj;
|
||||
return generate(obj);
|
||||
}
|
||||
|
||||
template< class Type >
|
||||
std::vector<column> generate(const Type &obj) {
|
||||
std::vector<table_column> generate(const Type &obj) {
|
||||
result_.clear();
|
||||
access::process(*this, obj);
|
||||
|
||||
|
|
@ -148,7 +146,7 @@ private:
|
|||
|
||||
private:
|
||||
std::optional<std::reference_wrapper<const schema>> repo_;
|
||||
std::vector<column> result_;
|
||||
std::vector<table_column> result_;
|
||||
std::stack<std::shared_ptr<table>> table_stack_;
|
||||
std::unordered_set<std::string> seen_tables;
|
||||
int column_index{0};
|
||||
|
|
@ -295,7 +293,7 @@ std::vector<internal::column_value_pair> column_value_pairs() {
|
|||
}
|
||||
|
||||
template<typename Type>
|
||||
std::vector<column> columns(const schema &repo,
|
||||
std::vector<table_column> columns(const schema &repo,
|
||||
const std::string &table_name = "",
|
||||
const column_generator_options options = default_column_generator_options) {
|
||||
column_generator generator(repo, table_name, options);
|
||||
|
|
@ -303,7 +301,7 @@ std::vector<column> columns(const schema &repo,
|
|||
}
|
||||
|
||||
template<typename Type>
|
||||
std::vector<column> columns(const schema &repo,
|
||||
std::vector<table_column> columns(const schema &repo,
|
||||
const column_generator_options options) {
|
||||
std::string table_name;
|
||||
if (const auto result = repo.repo().info<Type>()) {
|
||||
|
|
@ -314,7 +312,7 @@ std::vector<column> columns(const schema &repo,
|
|||
}
|
||||
|
||||
template<typename Type>
|
||||
std::vector<column> columns(const Type &obj,
|
||||
std::vector<table_column> columns(const Type &obj,
|
||||
const schema &repo,
|
||||
const std::string &table_name = "",
|
||||
const column_generator_options options = default_column_generator_options) {
|
||||
|
|
@ -322,20 +320,5 @@ std::vector<column> columns(const Type &obj,
|
|||
return generator.generate(obj);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
std::vector<column> columns(const std::string &table_name = "",
|
||||
const column_generator_options options = default_column_generator_options) {
|
||||
column_generator generator(table_name, options);
|
||||
return generator.generate<Type>();
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
std::vector<column> columns(const Type &obj,
|
||||
const std::string &table_name = "",
|
||||
const column_generator_options options = default_column_generator_options) {
|
||||
column_generator generator(table_name, options);
|
||||
return generator.generate(obj);
|
||||
}
|
||||
|
||||
}
|
||||
#endif //MATADOR_GENERATOR_HPP
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "matador/query/intermediates/executable_query.hpp"
|
||||
#include "matador/query/intermediates/query_intermediate.hpp"
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
|
||||
#include "matador/object/restriction.hpp"
|
||||
|
||||
|
|
@ -16,21 +16,21 @@ class query_add_foreign_key_constraint_intermediate final : public query_interme
|
|||
public:
|
||||
using query_intermediate::query_intermediate;
|
||||
|
||||
executable_query references(const table& tab, const std::vector<column>& columns = {});
|
||||
executable_query references(const table& tab, const std::vector<table_column>& columns = {});
|
||||
|
||||
private:
|
||||
table table_;
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_add_key_constraint_intermediate final : public query_intermediate {
|
||||
public:
|
||||
using query_intermediate::query_intermediate;
|
||||
|
||||
[[nodiscard]] query_add_primary_key_constraint_intermediate primary_key(const column& col) const;
|
||||
[[nodiscard]] query_add_primary_key_constraint_intermediate primary_keys(const std::vector<column>& columns) const;
|
||||
[[nodiscard]] query_add_foreign_key_constraint_intermediate foreign_key(const column& col) const;
|
||||
[[nodiscard]] query_add_foreign_key_constraint_intermediate foreign_keys(const std::vector<column>& columns) const;
|
||||
[[nodiscard]] query_add_primary_key_constraint_intermediate primary_key(const table_column& col) const;
|
||||
[[nodiscard]] query_add_primary_key_constraint_intermediate primary_keys(const std::vector<table_column>& columns) const;
|
||||
[[nodiscard]] query_add_foreign_key_constraint_intermediate foreign_key(const table_column& col) const;
|
||||
[[nodiscard]] query_add_foreign_key_constraint_intermediate foreign_keys(const std::vector<table_column>& columns) const;
|
||||
};
|
||||
|
||||
class query_alter_table_intermediate final : public query_intermediate {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "matador/query/intermediates/executable_query.hpp"
|
||||
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
|
||||
#include "matador/object/attribute.hpp"
|
||||
#include "matador/object/restriction.hpp"
|
||||
|
|
@ -20,8 +20,8 @@ public:
|
|||
|
||||
executable_query constraints(std::initializer_list<object::restriction> constraints);
|
||||
executable_query constraints(const std::list<object::restriction> &restrictions);
|
||||
executable_query constraints(std::initializer_list<constraint> constraints);
|
||||
executable_query constraints(const std::list<constraint> &restrictions);
|
||||
executable_query constraints(std::initializer_list<table_constraint> constraints);
|
||||
executable_query constraints(const std::list<table_constraint> &restrictions);
|
||||
};
|
||||
|
||||
class query_create_table_intermediate : public query_intermediate {
|
||||
|
|
@ -30,8 +30,8 @@ public:
|
|||
|
||||
query_create_table_columns_intermediate columns(std::initializer_list<object::attribute> attributes);
|
||||
query_create_table_columns_intermediate columns(const std::list<object::attribute> &attributes);
|
||||
query_create_table_columns_intermediate columns(std::initializer_list<column> columns);
|
||||
query_create_table_columns_intermediate columns(const std::list<column> &columns);
|
||||
query_create_table_columns_intermediate columns(std::initializer_list<table_column> columns);
|
||||
query_create_table_columns_intermediate columns(const std::list<table_column> &columns);
|
||||
};
|
||||
|
||||
class query_create_intermediate : public query_intermediate {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public:
|
|||
using executable_query::executable_query;
|
||||
|
||||
query_execute_limit_intermediate limit(size_t limit);
|
||||
query_execute_order_by_intermediate order_by(const column &col);
|
||||
query_execute_order_by_intermediate order_by(const table_column &col);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ public:
|
|||
// return where_clause(std::make_unique<Condition>(std::move(cond)));
|
||||
// }
|
||||
query_where_intermediate where(std::unique_ptr<abstract_criteria> &&cond);
|
||||
query_group_by_intermediate group_by(const column &col);
|
||||
query_order_by_intermediate order_by(const column &col);
|
||||
query_group_by_intermediate group_by(const table_column &col);
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
|
||||
private:
|
||||
query_where_intermediate where_clause(std::unique_ptr<abstract_criteria> &&cond);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class query_group_by_intermediate : public fetchable_query
|
|||
public:
|
||||
using fetchable_query::fetchable_query;
|
||||
|
||||
query_order_by_intermediate order_by(const column &col);
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,22 +3,21 @@
|
|||
|
||||
#include "matador/query/intermediates/query_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||
|
||||
#include "matador/query/schema.hpp"
|
||||
#include "matador/query/generator.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
class query_insert_intermediate : public query_intermediate
|
||||
{
|
||||
class query_insert_intermediate : public query_intermediate {
|
||||
public:
|
||||
query_insert_intermediate();
|
||||
|
||||
template<class Type>
|
||||
query_into_intermediate into(const table &tab, const object::repository &schema) {
|
||||
return into(tab, generator::columns<Type>(schema));
|
||||
query_into_intermediate into(const table &tab, const schema &scm) {
|
||||
return into(tab, generator::columns<Type>(scm));
|
||||
}
|
||||
query_into_intermediate into(const table &tab, std::initializer_list<column> columns);
|
||||
query_into_intermediate into(const table &tab, std::vector<column> &&columns);
|
||||
query_into_intermediate into(const table &tab, std::initializer_list<table_column> columns);
|
||||
query_into_intermediate into(const table &tab, std::vector<table_column> &&columns);
|
||||
query_into_intermediate into(const table &tab, const std::vector<std::string> &column_names);
|
||||
query_into_intermediate into(const table &tab);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class query_from_intermediate;
|
|||
class query_select_intermediate : public query_intermediate
|
||||
{
|
||||
public:
|
||||
explicit query_select_intermediate(const std::vector<column>& columns);
|
||||
explicit query_select_intermediate(const std::vector<table_column>& columns);
|
||||
|
||||
query_from_intermediate from(const table& t);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ class query_where_intermediate : public fetchable_query
|
|||
public:
|
||||
using fetchable_query::fetchable_query;
|
||||
|
||||
query_group_by_intermediate group_by(const column &col);
|
||||
query_order_by_intermediate order_by(const column &col);
|
||||
query_group_by_intermediate group_by(const table_column &col);
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef QUERY_KEY_VALUE_PAIR_HPP
|
||||
#define QUERY_KEY_VALUE_PAIR_HPP
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "matador/utils/placeholder.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
|
@ -10,7 +10,7 @@ namespace matador::query::internal {
|
|||
|
||||
class column_value_pair {
|
||||
public:
|
||||
column_value_pair(const column &col, utils::database_type value);
|
||||
column_value_pair(const table_column &col, utils::database_type value);
|
||||
column_value_pair(std::string name, utils::database_type value);
|
||||
column_value_pair(const char *name, utils::database_type value);
|
||||
column_value_pair(const char *name, utils::placeholder p);
|
||||
|
|
@ -18,11 +18,11 @@ public:
|
|||
friend bool operator==(const column_value_pair &lhs, const column_value_pair &rhs);
|
||||
friend bool operator!=(const column_value_pair &lhs, const column_value_pair &rhs);
|
||||
|
||||
[[nodiscard]] const column& col() const;
|
||||
[[nodiscard]] const table_column& col() const;
|
||||
[[nodiscard]] const std::variant<utils::placeholder, utils::database_type>& value() const;
|
||||
|
||||
private:
|
||||
column column_;
|
||||
table_column column_;
|
||||
std::variant<utils::placeholder, utils::database_type> value_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "matador/query/internal/column_value_pair.hpp"
|
||||
#include "matador/query/query_part.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
#include "matador/utils/placeholder.hpp"
|
||||
|
|
@ -50,12 +50,12 @@ private:
|
|||
|
||||
class query_add_constraint_part_by_constraint final : public query_part {
|
||||
public:
|
||||
explicit query_add_constraint_part_by_constraint(const constraint& co);
|
||||
explicit query_add_constraint_part_by_constraint(const table_constraint& co);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const class constraint& constraint() const;
|
||||
[[nodiscard]] const table_constraint& constraint() const;
|
||||
private:
|
||||
class constraint constraint_;
|
||||
table_constraint constraint_;
|
||||
};
|
||||
|
||||
class query_drop_key_constraint_part_by_name final : public query_part {
|
||||
|
|
@ -70,45 +70,45 @@ private:
|
|||
|
||||
class query_drop_key_constraint_part_by_constraint final : public query_part {
|
||||
public:
|
||||
explicit query_drop_key_constraint_part_by_constraint(const constraint& co);
|
||||
explicit query_drop_key_constraint_part_by_constraint(const table_constraint& co);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const class constraint& constraint() const;
|
||||
[[nodiscard]] const table_constraint& constraint() const;
|
||||
private:
|
||||
class constraint constraint_;
|
||||
table_constraint constraint_;
|
||||
};
|
||||
|
||||
class query_add_foreign_key_constraint_part final : public query_part {
|
||||
public:
|
||||
explicit query_add_foreign_key_constraint_part( const std::vector<column>& columns);
|
||||
explicit query_add_foreign_key_constraint_part( const std::vector<table_column>& columns);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
private:
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_add_foreign_key_reference_part final : public query_part {
|
||||
public:
|
||||
explicit query_add_foreign_key_reference_part(class table tab, const std::vector<column>& columns);
|
||||
explicit query_add_foreign_key_reference_part(class table tab, const std::vector<table_column>& columns);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const class table& table() const;
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
query::table table_;
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_add_primary_key_constraint_part final : public query_part {
|
||||
public:
|
||||
explicit query_add_primary_key_constraint_part( const std::vector<column>& columns);
|
||||
explicit query_add_primary_key_constraint_part( const std::vector<table_column>& columns);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
private:
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -117,13 +117,13 @@ private:
|
|||
class query_select_part final : public query_part
|
||||
{
|
||||
public:
|
||||
explicit query_select_part(std::vector<column> columns);
|
||||
explicit query_select_part(std::vector<table_column> columns);
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -205,29 +205,29 @@ protected:
|
|||
class query_group_by_part final : public query_part
|
||||
{
|
||||
public:
|
||||
explicit query_group_by_part(class column col);
|
||||
explicit query_group_by_part(class table_column col);
|
||||
|
||||
[[nodiscard]] const class column& column() const;
|
||||
[[nodiscard]] const table_column& column() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
class column column_;
|
||||
table_column column_;
|
||||
};
|
||||
|
||||
class query_order_by_part final : public query_part
|
||||
{
|
||||
public:
|
||||
explicit query_order_by_part(class column col);
|
||||
explicit query_order_by_part(class table_column col);
|
||||
|
||||
[[nodiscard]] const class column& column() const;
|
||||
[[nodiscard]] const table_column& column() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
class column column_;
|
||||
table_column column_;
|
||||
};
|
||||
|
||||
class query_order_by_asc_part final : public query_part
|
||||
|
|
@ -288,17 +288,17 @@ private:
|
|||
class query_into_part final : public query_part
|
||||
{
|
||||
public:
|
||||
query_into_part(class table tab, std::vector<column> columns);
|
||||
query_into_part(class table tab, std::vector<table_column> columns);
|
||||
|
||||
[[nodiscard]] const class table& table() const;
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
class table table_;
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
/**
|
||||
* Represents the SQL VALUES part
|
||||
|
|
@ -393,28 +393,28 @@ private:
|
|||
|
||||
class query_create_table_columns_part final : public query_part {
|
||||
public:
|
||||
explicit query_create_table_columns_part(const std::list<column> &columns);
|
||||
explicit query_create_table_columns_part(const std::list<table_column> &columns);
|
||||
|
||||
[[nodiscard]] const std::list<column>& columns() const;
|
||||
[[nodiscard]] const std::list<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
std::list<column> columns_;
|
||||
std::list<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_create_table_constraints_part final : public query_part {
|
||||
public:
|
||||
explicit query_create_table_constraints_part(const std::list<constraint> &constraints);
|
||||
explicit query_create_table_constraints_part(const std::list<table_constraint> &constraints);
|
||||
|
||||
[[nodiscard]] const std::list<constraint>& constraints() const;
|
||||
[[nodiscard]] const std::list<table_constraint>& constraints() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
std::list<constraint> constraints_;
|
||||
std::list<table_constraint> constraints_;
|
||||
};
|
||||
|
||||
class query_create_schema_part final : public query_part {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef MATADOR_META_TABLE_MACRO_HPP
|
||||
#define MATADOR_META_TABLE_MACRO_HPP
|
||||
|
||||
#include "matador/utils/macro_map.hpp"
|
||||
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
#define FIELD(FIELD_NAME) const matador::query::table_column& FIELD_NAME;
|
||||
#define INIT_FIELD(FIELD_NAME) , FIELD_NAME(*column_by_name(*this, #FIELD_NAME))
|
||||
#define FIELD_STRING(FIELD_NAME) #FIELD_NAME,
|
||||
|
||||
#define META_TABLE(TABLE_NAME, VARIABLE_NAME, ...) \
|
||||
namespace matador::query::meta { \
|
||||
namespace internal { \
|
||||
class TABLE_NAME##_table : public typed_table<TABLE_NAME##_table> { \
|
||||
public: \
|
||||
TABLE_NAME##_table()\
|
||||
: TABLE_NAME##_table("") \
|
||||
{} \
|
||||
TABLE_NAME##_table(const std::string& alias) \
|
||||
: typed_table(#TABLE_NAME, alias, {MAP(FIELD_STRING, __VA_ARGS__)}) \
|
||||
MAP(INIT_FIELD, __VA_ARGS__) \
|
||||
{} \
|
||||
MAP(FIELD, __VA_ARGS__) \
|
||||
}; } \
|
||||
static const internal:: TABLE_NAME##_table VARIABLE_NAME; \
|
||||
}
|
||||
|
||||
#endif //MATADOR_META_TABLE_MACRO_HPP
|
||||
|
|
@ -4,16 +4,17 @@
|
|||
#include "matador/query/query_intermediates.hpp"
|
||||
|
||||
#include "matador/query/generator.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
class connection;
|
||||
}
|
||||
namespace matador::query {
|
||||
|
||||
column alias(const std::string &column, const std::string &as);
|
||||
column alias(column &&col, const std::string &as);
|
||||
column count(const std::string &column);
|
||||
column count_all();
|
||||
table_column alias(const std::string &column, const std::string &as);
|
||||
table_column alias(table_column &&col, const std::string &as);
|
||||
table_column count(const std::string &column);
|
||||
table_column count_all();
|
||||
|
||||
class query
|
||||
{
|
||||
|
|
@ -21,13 +22,13 @@ public:
|
|||
[[nodiscard]] static query_create_intermediate create();
|
||||
[[nodiscard]] static query_drop_intermediate drop();
|
||||
[[nodiscard]] static query_select_intermediate select();
|
||||
[[nodiscard]] static query_select_intermediate select(std::initializer_list<column> columns);
|
||||
[[nodiscard]] static query_select_intermediate select(const std::vector<column>& columns);
|
||||
[[nodiscard]] static query_select_intermediate select(std::initializer_list<table_column> columns);
|
||||
[[nodiscard]] static query_select_intermediate select(const std::vector<table_column>& columns);
|
||||
[[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names);
|
||||
[[nodiscard]] static query_select_intermediate select(std::vector<column> columns, std::initializer_list<column> additional_columns);
|
||||
[[nodiscard]] static query_select_intermediate select(std::vector<table_column> columns, std::initializer_list<table_column> additional_columns);
|
||||
template<class Type>
|
||||
[[nodiscard]] static query_select_intermediate select(const object::repository &schema) {
|
||||
return select(generator::columns<Type>(schema));
|
||||
[[nodiscard]] static query_select_intermediate select(const schema &scm) {
|
||||
return select(generator::columns<Type>(scm));
|
||||
}
|
||||
[[nodiscard]] static query_insert_intermediate insert();
|
||||
[[nodiscard]] static query_update_intermediate update(const table &table);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ namespace internal {
|
|||
struct basic_type_to_string_visitor;
|
||||
}
|
||||
|
||||
class table_constraint;
|
||||
|
||||
struct query_data;
|
||||
struct value_visitor;
|
||||
|
||||
|
|
@ -77,9 +79,9 @@ protected:
|
|||
static std::string build_table_name(sql::dialect_token token, const sql::dialect &d, const table& t);
|
||||
static std::string determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val);
|
||||
|
||||
std::string build_add_constraint_string(const class constraint& c);
|
||||
std::string build_drop_constraint_string(const class constraint& c);
|
||||
std::string build_constraint_name(const class constraint& c);
|
||||
[[nodiscard]] std::string build_add_constraint_string(const table_constraint& c) const;
|
||||
[[nodiscard]] std::string build_drop_constraint_string(const table_constraint& c) const;
|
||||
static std::string build_constraint_name(const table_constraint& c);
|
||||
|
||||
protected:
|
||||
const query_data *data_{};
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@ namespace matador::sql {
|
|||
class dialect;
|
||||
}
|
||||
namespace matador::query {
|
||||
class column;
|
||||
class table_column;
|
||||
|
||||
[[nodiscard]] std::string prepare_identifier(const sql::dialect& d, const column &col);
|
||||
[[nodiscard]] std::string prepare_identifier(const sql::dialect& d, const table &tab, const column &col);
|
||||
[[nodiscard]] std::string prepare_criteria(const sql::dialect& d, const column &col);
|
||||
[[nodiscard]] std::string prepare_identifier(const sql::dialect& d, const table_column &col);
|
||||
[[nodiscard]] std::string prepare_criteria(const sql::dialect& d, const table_column &col);
|
||||
}
|
||||
#endif //MATADOR_QUERY_UTILS_HPP
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
namespace matador::sql {
|
||||
class connection_pool;
|
||||
class connection;
|
||||
}
|
||||
|
||||
namespace matador::query {
|
||||
|
|
@ -34,20 +35,42 @@ class schema_observer final : public object::observer<Type> {
|
|||
public:
|
||||
explicit schema_observer(schema& s)
|
||||
: schema_(s) {}
|
||||
void on_attach(object::repository_node &node, const Type &prototype) override;
|
||||
void on_detach(object::repository_node &node, const Type &prototype) override;
|
||||
void on_insert(Type &obj) override;
|
||||
void on_update(Type &obj) override;
|
||||
void on_delete(Type &obj) override;
|
||||
template<typename OtherType>
|
||||
explicit schema_observer(const schema_observer<OtherType> &x)
|
||||
: schema_(x.schema_)
|
||||
{}
|
||||
void on_attach(const object::repository_node &node, const Type &prototype) const override;
|
||||
void on_detach(const object::repository_node &node, const Type &prototype) const override;
|
||||
void on_insert(const Type &obj) override;
|
||||
void on_update(const Type &obj) override;
|
||||
void on_delete(const Type &obj) override;
|
||||
|
||||
private:
|
||||
template < class OtherType >
|
||||
friend class schema_observer;
|
||||
|
||||
schema& schema_;
|
||||
};
|
||||
|
||||
class schema_node final {
|
||||
public:
|
||||
schema_node(class table tab, const object::repository_node& node);
|
||||
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
[[nodiscard]] const class table& table() const;
|
||||
[[nodiscard]] const object::repository_node& node() const;
|
||||
|
||||
private:
|
||||
class table table_;
|
||||
const object::repository_node& node_;
|
||||
};
|
||||
class schema final {
|
||||
public:
|
||||
explicit schema(sql::connection_pool &pool);
|
||||
schema(sql::connection_pool &pool, const std::string &name);
|
||||
using iterator = std::unordered_map<std::type_index, schema_node>::iterator;
|
||||
using const_iterator = std::unordered_map<std::type_index, schema_node>::const_iterator;
|
||||
|
||||
schema() = default;
|
||||
explicit schema(const std::string &name);
|
||||
|
||||
template<typename Type, typename... Observers>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||
|
|
@ -64,21 +87,33 @@ public:
|
|||
return repo_.attach<Type, SuperType>(name, schema_observer<Type>{*this}, std::forward<Observers>(observers)...);
|
||||
}
|
||||
|
||||
[[nodiscard]] utils::result<void, utils::error> create() const;
|
||||
[[nodiscard]] utils::result<void, utils::error> drop() const;
|
||||
[[nodiscard]] utils::result<void, utils::error> create(const sql::connection &conn) const;
|
||||
[[nodiscard]] utils::result<void, utils::error> drop(const sql::connection &conn) const;
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> drop_table();
|
||||
[[nodiscard]] utils::result<void, utils::error> drop_table(const std::string &table_name) const;
|
||||
[[nodiscard]] utils::result<void, utils::error> drop_table(const sql::connection &conn);
|
||||
[[nodiscard]] utils::result<void, utils::error> drop_table(const std::string &table_name, const sql::connection &conn) const;
|
||||
|
||||
[[nodiscard]] utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name) const;
|
||||
[[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name) const;
|
||||
[[nodiscard]] utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name, const sql::connection &conn) const;
|
||||
[[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name, const sql::connection &conn) const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
iterator find(const std::type_index& ti) { return schema_nodes_.find(ti); }
|
||||
const_iterator find(const std::type_index& ti) const { return schema_nodes_.find(ti); }
|
||||
|
||||
iterator find(const std::string& name);
|
||||
const_iterator find(const std::string& name) const;
|
||||
|
||||
const object::repository &repo() const { return repo_; }
|
||||
object::repository &repo() { return repo_; }
|
||||
|
||||
private:
|
||||
[[nodiscard]] sql::query_context build_add_constraint_context( const object::repository_node& node, const object::restriction& cons ) const;
|
||||
[[nodiscard]] sql::query_context build_drop_constraint_context( const object::repository_node& node, const object::restriction& cons ) const;
|
||||
[[nodiscard]] sql::query_context build_add_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) const;
|
||||
[[nodiscard]] sql::query_context build_drop_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) const;
|
||||
|
||||
void insert_table(const std::type_index& ti, const object::repository_node &node);
|
||||
|
||||
|
|
@ -87,31 +122,30 @@ private:
|
|||
friend class schema_observer;
|
||||
|
||||
object::repository repo_;
|
||||
std::unordered_map<std::type_index, table> tables_;
|
||||
sql::connection_pool &pool_;
|
||||
std::unordered_map<std::type_index, schema_node> schema_nodes_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
utils::result<void, utils::error> schema::drop_table() {
|
||||
utils::result<void, utils::error> schema::drop_table(const sql::connection &conn) {
|
||||
auto info = repo_.info<Type>();
|
||||
if (info) {
|
||||
return drop_table(info->get().name());
|
||||
return drop_table(info->get().name(), conn);
|
||||
}
|
||||
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
template <typename Type>
|
||||
void schema_observer<Type>::on_attach(object::repository_node &node, const Type &prototype) {
|
||||
void schema_observer<Type>::on_attach(const object::repository_node &node, const Type &/*prototype*/) const {
|
||||
schema_.insert_table(typeid(Type), node);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void schema_observer<Type>::on_detach(object::repository_node &node, const Type &prototype) {}
|
||||
void schema_observer<Type>::on_detach(const object::repository_node &/*node*/, const Type &/*prototype*/) const {}
|
||||
template <typename Type>
|
||||
void schema_observer<Type>::on_insert(Type &obj) {}
|
||||
void schema_observer<Type>::on_insert(const Type &/*obj*/) {}
|
||||
template <typename Type>
|
||||
void schema_observer<Type>::on_update(Type &obj) {}
|
||||
void schema_observer<Type>::on_update(const Type &/*obj*/) {}
|
||||
template <typename Type>
|
||||
void schema_observer<Type>::on_delete(Type &obj) {}
|
||||
void schema_observer<Type>::on_delete(const Type &/*obj*/) {}
|
||||
} // namespace matador::query
|
||||
#endif //MATADOR_SCHEMA_HPP
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef QUERY_TABLE_HPP
|
||||
#define QUERY_TABLE_HPP
|
||||
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
@ -13,36 +13,54 @@ class table {
|
|||
public:
|
||||
table() = default;
|
||||
table(const char *name); // NOLINT(*-explicit-constructor)
|
||||
table(std::string name); // NOLINT(*-explicit-constructor)
|
||||
table(std::string name, std::string as);
|
||||
table(std::string name, std::string as, const std::vector<column> &columns);
|
||||
table(const std::string& name); // NOLINT(*-explicit-constructor)
|
||||
table(const std::string& name, const std::vector<table_column>& columns);
|
||||
table(const table& other);
|
||||
table& operator=(const table& other);
|
||||
table(table&& other) noexcept;
|
||||
table& operator=(table&& other) noexcept;
|
||||
~table() = default;
|
||||
|
||||
table as(const std::string &a);
|
||||
[[nodiscard]] table as(const std::string &alias) const;
|
||||
|
||||
[[nodiscard]] bool operator==(const table &x) const;
|
||||
|
||||
[[nodiscard]] table as(const std::string &a) const;
|
||||
[[nodiscard]] const std::string& table_name() const;
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
[[nodiscard]] bool has_alias() const;
|
||||
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
[[nodiscard]] const std::string& alias() const;
|
||||
[[nodiscard]] const std::vector<column>& columns() const;
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator const std::vector<query::column>&() const; // NOLINT(*-explicit-constructor)
|
||||
operator const std::vector<query::table_column>&() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
const table_column* operator[](const std::string& column_name) const;
|
||||
static const table_column* column_by_name(const table &tab, const std::string& column_name);
|
||||
|
||||
protected:
|
||||
static const table_column& create_column(class table& tab, const std::string& name);
|
||||
|
||||
table(std::string name, std::string alias, const std::vector<table_column>& columns);
|
||||
|
||||
private:
|
||||
friend class column;
|
||||
friend table_column;
|
||||
|
||||
std::string name_;
|
||||
std::string alias_;
|
||||
|
||||
std::string schema_name_;
|
||||
std::vector<column> columns_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
table operator ""_tab(const char *name, size_t len);
|
||||
|
||||
template<typename Type>
|
||||
class typed_table : public table {
|
||||
public:
|
||||
using table::table;
|
||||
|
||||
Type as(std::string alias) const { return Type{std::move(alias)}; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif //QUERY_TABLE_HPP
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef QUERY_COLUMN_HPP
|
||||
#define QUERY_COLUMN_HPP
|
||||
|
||||
#include "matador/sql/sql_functions.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
class table;
|
||||
|
||||
// ReSharper disable CppNonExplicitConvertingConstructor
|
||||
class table_column {
|
||||
public:
|
||||
table_column(const char *name); // NOLINT(*-explicit-constructor)
|
||||
table_column(std::string name); // NOLINT(*-explicit-constructor)
|
||||
table_column(std::string name, std::string alias);
|
||||
table_column(sql::sql_function_t func, std::string name);
|
||||
table_column(const class table* tab, std::string name);
|
||||
table_column(const class table* tab, std::string name, std::string alias);
|
||||
table_column(const class table* tab, std::string name, utils::basic_type type, const utils::field_attributes& attributes);
|
||||
table_column(const class table*, std::string name, std::string alias, utils::basic_type type, const utils::field_attributes& attributes, sql::sql_function_t func = sql::sql_function_t::None);
|
||||
table_column& operator=(const table_column& other);
|
||||
table_column(const table_column& other) = default;
|
||||
table_column(table_column&& other) noexcept = default;
|
||||
~table_column() = default;
|
||||
|
||||
[[nodiscard]] bool equals(const table_column &x) const;
|
||||
|
||||
table_column as(std::string a);
|
||||
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
[[nodiscard]] std::string canonical_name() const;
|
||||
[[nodiscard]] const std::string& alias() const;
|
||||
[[nodiscard]] utils::basic_type type() const;
|
||||
[[nodiscard]] utils::field_attributes attributes() const;
|
||||
|
||||
[[nodiscard]] bool is_function() const;
|
||||
[[nodiscard]] bool is_nullable() const;
|
||||
[[nodiscard]] sql::sql_function_t function() const;
|
||||
[[nodiscard]] bool has_alias() const;
|
||||
|
||||
[[nodiscard]] const class table* table() const;
|
||||
void table(const query::table* tab);
|
||||
|
||||
// ReSharper disable once CppNonExplicitConversionOperator
|
||||
operator const std::string&() const; // NOLINT(*-explicit-constructor)
|
||||
|
||||
private:
|
||||
friend class table;
|
||||
|
||||
const class table* table_{nullptr};
|
||||
std::string name_;
|
||||
std::string alias_;
|
||||
utils::basic_type type_{utils::basic_type::Unknown};
|
||||
utils::field_attributes attributes_{};
|
||||
|
||||
sql::sql_function_t function_{sql::sql_function_t::None};
|
||||
};
|
||||
|
||||
table_column operator ""_col(const char *name, size_t len);
|
||||
|
||||
}
|
||||
#endif //QUERY_COLUMN_HPP
|
||||
|
|
@ -8,12 +8,14 @@ enum class constraints : unsigned char;
|
|||
}
|
||||
|
||||
namespace matador::query {
|
||||
class constraint {
|
||||
class table_constraint {
|
||||
public:
|
||||
constraint() = default;
|
||||
constraint(std::string column_name, std::string table_name, utils::constraints type);
|
||||
constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column);
|
||||
table_constraint() = default;
|
||||
table_constraint(std::string column_name, std::string table_name, utils::constraints type);
|
||||
table_constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column);
|
||||
table_constraint(std::string name, std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column);
|
||||
|
||||
[[nodiscard]] std::string name() const;
|
||||
[[nodiscard]] std::string column_name() const;
|
||||
[[nodiscard]] std::string table_name() const;
|
||||
[[nodiscard]] const utils::constraints& type() const;
|
||||
|
|
@ -24,6 +26,7 @@ public:
|
|||
[[nodiscard]] const std::string& referenced_column() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string column_name_;
|
||||
std::string table_name_;
|
||||
utils::constraints type_{};
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef QUERY_QUERY_HELPER_HPP
|
||||
#define QUERY_QUERY_HELPER_HPP
|
||||
|
||||
#include "matador/utils/macro_map.hpp"
|
||||
|
||||
#include "matador/query/table.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
#define FIELD(x) const matador::query::column x{*this, #x, ""};
|
||||
|
||||
#define QUERY_HELPER(C, V, ...) \
|
||||
namespace matador::query::meta { \
|
||||
namespace internal { \
|
||||
struct C##_query : table { \
|
||||
C##_query() : table(#C) {} \
|
||||
MAP(FIELD, __VA_ARGS__) \
|
||||
}; } \
|
||||
static const internal:: C##_query V; \
|
||||
}
|
||||
|
||||
#endif //QUERY_QUERY_HELPER_HPP
|
||||
|
|
@ -108,6 +108,8 @@ add_library(matador-core STATIC
|
|||
utils/uuid.cpp
|
||||
utils/value.cpp
|
||||
utils/version.cpp
|
||||
../../include/matador/object/internal/observer_list_creator.hpp
|
||||
../../include/matador/object/internal/observer_list_copy_creator.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ attribute::attribute(std::string name,
|
|||
: name_(std::move(name))
|
||||
, type_(type)
|
||||
, options_(attr)
|
||||
, null_option_(null_opt)
|
||||
{}
|
||||
, null_option_(null_opt) {
|
||||
}
|
||||
|
||||
const std::string &attribute::name() const {
|
||||
return name_;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "matador/object/repository_node.hpp"
|
||||
|
||||
namespace matador::object::internal {
|
||||
shadow_repository::shadow_repository( repository& s )
|
||||
shadow_repository::shadow_repository(repository& s)
|
||||
: repo_(s) {}
|
||||
|
||||
repository& shadow_repository::repo() const {
|
||||
|
|
@ -62,4 +62,20 @@ std::shared_ptr<object> shadow_repository::object_for_type(const std::type_index
|
|||
void shadow_repository::remove_object_for_type(const std::type_index& ti) const {
|
||||
repo_.remove_object_for_type(ti);
|
||||
}
|
||||
|
||||
bool shadow_repository::is_node_announced(const std::type_index &ti) const {
|
||||
return repo_.is_node_announced(ti);
|
||||
}
|
||||
|
||||
void shadow_repository::push_announce_node(const std::type_index &ti, const node_ptr &node) const {
|
||||
repo_.push_announce_node(ti, node);
|
||||
}
|
||||
|
||||
shadow_repository::node_ptr shadow_repository::announce_node(const std::type_index &ti) const {
|
||||
return repo_.announce_node(ti);
|
||||
}
|
||||
|
||||
shadow_repository::node_ptr shadow_repository::pop_announce_node(const std::type_index &ti) const {
|
||||
return repo_.pop_announce_node(ti);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace matador::object {
|
||||
object_generator::object_generator(repository& repo, const std::shared_ptr<object>& object)
|
||||
object_generator::object_generator(const repository& repo, const std::shared_ptr<object>& object)
|
||||
: repo_(repo)
|
||||
, object_(object) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,8 +104,7 @@ void repository::dump( std::ostream& os, const node_ptr& node ) {
|
|||
}
|
||||
}
|
||||
|
||||
utils::result<repository::node_ptr, utils::error> repository::attach_node(const std::shared_ptr<repository_node> &node,
|
||||
const std::string &parent) {
|
||||
utils::result<repository::node_ptr, utils::error> repository::attach_node(const std::shared_ptr<repository_node> &node, const std::string &parent) {
|
||||
if (has_node(node)) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
|
||||
}
|
||||
|
|
@ -233,4 +232,24 @@ std::shared_ptr<object> repository::object_for_type(const std::type_index &ti) c
|
|||
void repository::remove_object_for_type(const std::type_index &ti) {
|
||||
object_by_type_.erase(ti);
|
||||
}
|
||||
|
||||
bool repository::is_node_announced(const std::type_index &ti) const {
|
||||
return announced_node_.count(ti) > 0;
|
||||
}
|
||||
|
||||
void repository::push_announce_node(const std::type_index &ti, const node_ptr &node) {
|
||||
announced_node_.insert({ti, node});
|
||||
}
|
||||
|
||||
repository::node_ptr repository::announce_node(const std::type_index &ti) {
|
||||
return announced_node_.find(ti)->second;
|
||||
}
|
||||
|
||||
repository::node_ptr repository::pop_announce_node(const std::type_index &ti) {
|
||||
const auto it = announced_node_.find(ti);
|
||||
if (it != announced_node_.end()) {
|
||||
announced_node_.erase(it);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
} // namespace matador::object
|
||||
|
|
|
|||
|
|
@ -99,10 +99,4 @@ void repository_node::unlink() {
|
|||
next_sibling_.reset();
|
||||
previous_sibling_.reset();
|
||||
}
|
||||
|
||||
utils::result<repository_node::node_ptr, utils::error> repository_node::make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti) {
|
||||
const auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, ti));
|
||||
|
||||
return repo.attach_node(node, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ add_library(matador-orm STATIC
|
|||
../../include/matador/orm/session_query_builder.hpp
|
||||
../../include/matador/query/attribute_string_writer.hpp
|
||||
../../include/matador/query/builder.hpp
|
||||
../../include/matador/query/column.hpp
|
||||
../../include/matador/query/constraint.hpp
|
||||
../../include/matador/query/criteria.hpp
|
||||
../../include/matador/query/criteria/abstract_column_criteria.hpp
|
||||
../../include/matador/query/criteria/abstract_criteria.hpp
|
||||
|
|
@ -51,6 +49,7 @@ add_library(matador-orm STATIC
|
|||
../../include/matador/query/internal/query_parts.hpp
|
||||
../../include/matador/query/join_data.hpp
|
||||
../../include/matador/query/key_value_generator.hpp
|
||||
../../include/matador/query/meta_table_macro.hpp
|
||||
../../include/matador/query/query.hpp
|
||||
../../include/matador/query/query_compiler.hpp
|
||||
../../include/matador/query/query_data.hpp
|
||||
|
|
@ -59,6 +58,8 @@ add_library(matador-orm STATIC
|
|||
../../include/matador/query/query_utils.hpp
|
||||
../../include/matador/query/schema.hpp
|
||||
../../include/matador/query/table.hpp
|
||||
../../include/matador/query/table_column.hpp
|
||||
../../include/matador/query/table_constraint.hpp
|
||||
../../include/matador/query/value_extractor.hpp
|
||||
../../include/matador/sql/abstract_sql_logger.hpp
|
||||
../../include/matador/sql/backend_provider.hpp
|
||||
|
|
@ -79,7 +80,6 @@ add_library(matador-orm STATIC
|
|||
../../include/matador/sql/internal/query_result_impl.hpp
|
||||
../../include/matador/sql/internal/query_result_pk_resolver.hpp
|
||||
../../include/matador/sql/query_context.hpp
|
||||
../../include/matador/sql/query_macro.hpp
|
||||
../../include/matador/sql/query_result.hpp
|
||||
../../include/matador/sql/record.hpp
|
||||
../../include/matador/sql/sql_functions.hpp
|
||||
|
|
@ -90,8 +90,6 @@ add_library(matador-orm STATIC
|
|||
orm/session_query_builder.cpp
|
||||
query/attribute_string_writer.cpp
|
||||
query/builder.cpp
|
||||
query/column.cpp
|
||||
query/constraint.cpp
|
||||
query/criteria/abstract_column_criteria.cpp
|
||||
query/criteria/between_criteria.cpp
|
||||
query/criteria/binary_criteria.cpp
|
||||
|
|
@ -140,6 +138,8 @@ add_library(matador-orm STATIC
|
|||
query/query_utils.cpp
|
||||
query/schema.cpp
|
||||
query/table.cpp
|
||||
query/table_column.cpp
|
||||
query/table_constraint.cpp
|
||||
query/value_extractor.cpp
|
||||
sql/backend_provider.cpp
|
||||
sql/connection.cpp
|
||||
|
|
@ -160,6 +160,7 @@ add_library(matador-orm STATIC
|
|||
sql/record.cpp
|
||||
sql/statement.cpp
|
||||
sql/statement_cache.cpp
|
||||
../../include/matador/query/meta_table_macro.hpp
|
||||
)
|
||||
|
||||
target_include_directories(matador-orm
|
||||
|
|
|
|||
|
|
@ -12,116 +12,10 @@ utils::error make_error(const error_code ec, const std::string &msg) {
|
|||
return utils::error(ec, msg);
|
||||
}
|
||||
|
||||
session::session(session_context&& ctx)
|
||||
session::session(session_context&& ctx, const query::schema &scm)
|
||||
: cache_(ctx.bus, ctx.pool, ctx.cache_size)
|
||||
, dialect_(sql::backend_provider::instance().connection_dialect(ctx.pool.info().type))
|
||||
, schema_(std::make_unique<object::repository>(dialect_.default_schema_name())) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> session::create_schema() const {
|
||||
// Step 1: Build dependency graph
|
||||
// std::unordered_map<std::string, std::vector<std::string> > dependency_graph;
|
||||
// std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree;
|
||||
|
||||
// for (const auto &node: *schema_) {
|
||||
// for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
|
||||
// dependency_graph[node->name()].push_back(it->second->node().name());
|
||||
//
|
||||
// if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) {
|
||||
// in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr());
|
||||
// } else {
|
||||
// in_degree[it->second->node().name()].first++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Ensure the current node exists in the graph representation
|
||||
// if (in_degree.find(node->name()) == in_degree.end()) {
|
||||
// in_degree[node->name()] = std::make_pair(0, node);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (const auto &it : dependency_graph) {
|
||||
// std::cout << "Dependency graph " << it.first << std::endl;
|
||||
// for (const auto &neighbor: it.second) {
|
||||
// std::cout << " " << neighbor << std::endl;
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// }
|
||||
|
||||
auto c = cache_.pool().acquire();
|
||||
for (const auto &node: *schema_) {
|
||||
auto ctx = query::query::create()
|
||||
.table(node->name())
|
||||
.columns(node->info().attributes())
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
// create table constraints
|
||||
for (const auto &node: *schema_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
auto ctx = build_add_constraint_context(node->name(), cons, c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
sql::query_context session::build_add_constraint_context(const std::string& table_name, const class object::restriction& cons, const sql::connection_ptr &conn) {
|
||||
if (cons.is_foreign_key_constraint()) {
|
||||
return query::query::alter()
|
||||
.table(table_name)
|
||||
.add_constraint(cons)
|
||||
.compile(*conn);
|
||||
}
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
return query::query::alter()
|
||||
.table(table_name)
|
||||
.add_constraint(cons)
|
||||
.compile(*conn);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> session::drop_schema() const {
|
||||
auto c = cache_.pool().acquire();
|
||||
// drop table constraints
|
||||
for (const auto &node: *schema_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.drop_constraint(cons)
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop table
|
||||
for (const auto &node: *schema_) {
|
||||
auto ctx = query::query::drop()
|
||||
.table(node->name())
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
, schema_(scm) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> session::drop_table(const std::string &table_name) const {
|
||||
|
|
@ -191,7 +85,7 @@ const class sql::dialect &session::dialect() const {
|
|||
}
|
||||
|
||||
void session::dump_schema(std::ostream &os) const {
|
||||
schema_->dump(os);
|
||||
schema_.repo().dump(os);
|
||||
}
|
||||
|
||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> session::fetch(const sql::query_context& ctx) const {
|
||||
|
|
@ -227,7 +121,7 @@ query::fetchable_query session::build_select_query(entity_query_data &&data) {
|
|||
.from(*data.root_table)
|
||||
.join_left(data.joins)
|
||||
.where(std::move(data.where_clause))
|
||||
.order_by({data.root_table.get(), data.pk_column_name})
|
||||
.order_by({data.root_table, data.pk_column_name})
|
||||
.asc();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <iostream>
|
||||
|
||||
namespace matador::orm {
|
||||
criteria_transformer::criteria_transformer(const query::schema& repo, const std::unordered_map<std::string, std::shared_ptr<query::table>>& tables_by_name)
|
||||
criteria_transformer::criteria_transformer(const query::schema& repo, const std::unordered_map<std::string, query::table>& tables_by_name)
|
||||
: repo_(repo)
|
||||
, tables_by_name_(tables_by_name) {}
|
||||
|
||||
|
|
@ -39,12 +39,15 @@ void criteria_transformer::visit( const query::not_criteria& node ) {
|
|||
}
|
||||
|
||||
void criteria_transformer::update_criteria_column(const query::abstract_column_criteria& node) const {
|
||||
const auto it = tables_by_name_.find(node.col().table()->name());
|
||||
if (it == tables_by_name_.end()) {
|
||||
return;
|
||||
}
|
||||
if (node.col().table() == nullptr) {
|
||||
return;
|
||||
}
|
||||
const auto it = tables_by_name_.find(node.col().table()->name());
|
||||
if (it == tables_by_name_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const_cast<query::column&>(node.col()).table(it->second.get());
|
||||
const_cast<query::table_column&>(node.col()).table(&it->second);
|
||||
}
|
||||
|
||||
void session_query_builder::on_revision(const char *id, uint64_t &/*rev*/) {
|
||||
|
|
@ -52,11 +55,11 @@ void session_query_builder::on_revision(const char *id, uint64_t &/*rev*/) {
|
|||
}
|
||||
|
||||
void session_query_builder::push(const std::string &column_name) {
|
||||
const auto it = processed_tables_.find(table_info_stack_.top().info.get().name());
|
||||
const auto it = processed_tables_.find(table_info_stack_.top().info.name());
|
||||
if (it == processed_tables_.end()) {
|
||||
throw query_builder_exception{query_build_error::UnexpectedError};
|
||||
}
|
||||
entity_query_data_.columns.emplace_back(it->second.get(), column_name, build_alias('c', ++column_index));
|
||||
entity_query_data_.columns.emplace_back(&it->second, column_name, build_alias('c', ++column_index));
|
||||
}
|
||||
|
||||
std::string session_query_builder::build_alias(const char prefix, const unsigned int count) {
|
||||
|
|
@ -70,7 +73,7 @@ std::string session_query_builder::build_alias(const char prefix, const unsigned
|
|||
return table_info_stack_.size() == 1;
|
||||
}
|
||||
|
||||
void session_query_builder::append_join(const query::column &left, const query::column &right) {
|
||||
void session_query_builder::append_join(const query::table_column &left, const query::table_column &right) {
|
||||
using namespace matador::query;
|
||||
entity_query_data_.joins.push_back({
|
||||
right.table(),
|
||||
|
|
|
|||
|
|
@ -4,52 +4,61 @@ namespace matador::query {
|
|||
|
||||
column_builder::column_builder(std::string column_name, const utils::basic_type type, const size_t size)
|
||||
: column_name_(std::move(column_name))
|
||||
, type_(type){}
|
||||
, type_(type)
|
||||
, size_(size) {}
|
||||
|
||||
column_builder::operator class query::column() const {
|
||||
return {column_name_};
|
||||
column_builder::operator class query::table_column() const {
|
||||
return {nullptr, column_name_, type_, {size_, constraints_}};
|
||||
}
|
||||
|
||||
column_builder& column_builder::not_null() {
|
||||
constraints_ |= utils::constraints::NotNull;
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
column_builder & column_builder::primary_key() {
|
||||
constraints_ |= utils::constraints::PrimaryKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
column_builder & column_builder::unique() {
|
||||
constraints_ |= utils::constraints::Unique;
|
||||
return *this;
|
||||
}
|
||||
|
||||
table_builder::table_builder(std::string name)
|
||||
: table_name( std::move(name) ) {}
|
||||
|
||||
table_builder& table_builder::as( std::string table_alias ) {
|
||||
this->alias = std::move(table_alias);
|
||||
return *this;
|
||||
}
|
||||
|
||||
table_builder::operator class query::table() const {
|
||||
return {table_name, alias, {}};
|
||||
return {table_name, {}};
|
||||
}
|
||||
|
||||
constraint_builder& constraint_builder::constraint( std::string name ) {
|
||||
constraint_name = std::move(name);
|
||||
constraint_name_ = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder& constraint_builder::primary_key( std::string name ) {
|
||||
pk_column_name = std::move(name);
|
||||
column_name_ = std::move(name);
|
||||
type_ = utils::constraints::PrimaryKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder& constraint_builder::foreign_key( std::string name ) {
|
||||
fk_column_name = std::move(name);
|
||||
column_name_ = std::move(name);
|
||||
type_ = utils::constraints::ForeignKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder& constraint_builder::references( std::string table, std::string column ) {
|
||||
this->table_name = std::move(table);
|
||||
this->column_name = std::move(column);
|
||||
this->ref_table_name_ = std::move(table);
|
||||
this->ref_column_name_ = std::move(column);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder::operator class constraint() const {
|
||||
return {};
|
||||
constraint_builder::operator table_constraint() const {
|
||||
return {constraint_name_, column_name_, ref_table_name_, type_, ref_table_name_, ref_column_name_};
|
||||
}
|
||||
|
||||
constraint_builder constraint( std::string name ) {
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
#include "matador/query/column.hpp"
|
||||
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
column operator ""_col(const char *name, const size_t len) {
|
||||
const std::string str(name, len);
|
||||
const auto pos = str.find('.');
|
||||
if (pos == std::string::npos) {
|
||||
return column{str};
|
||||
}
|
||||
|
||||
if (str.find('.', pos + 1) != std::string::npos) {
|
||||
throw std::invalid_argument("Invalid column name: multiple dots found");
|
||||
}
|
||||
|
||||
return column{new table(str.substr(0, pos)), str.substr(pos + 1)};
|
||||
}
|
||||
|
||||
column::column(const char *name)
|
||||
: column(std::string(name))
|
||||
{}
|
||||
|
||||
column::column(std::string name)
|
||||
: table_(default_table())
|
||||
, name_(std::move(name)) {}
|
||||
column::column(std::string name, std::string alias)
|
||||
: table_(default_table())
|
||||
, name_(std::move(name))
|
||||
, alias_(std::move(alias)) {}
|
||||
|
||||
column::column(const sql::sql_function_t func, std::string name)
|
||||
: table_(default_table())
|
||||
, name_(std::move(name))
|
||||
, function_(func) {}
|
||||
|
||||
column::column(const class table* tab, std::string name)
|
||||
: table_(tab)
|
||||
, name_(std::move(name)) {}
|
||||
|
||||
column::column(const class query::table* tab, std::string name, std::string alias)
|
||||
: table_(tab)
|
||||
, name_(std::move(name))
|
||||
, alias_(std::move(alias)) {}
|
||||
column::column(const class query::table* tab, std::string name,
|
||||
const utils::basic_type type,
|
||||
const utils::field_attributes& attributes)
|
||||
: table_(tab)
|
||||
, name_(std::move(name))
|
||||
, type_(type)
|
||||
, attributes_(attributes) {}
|
||||
|
||||
bool column::equals(const column &x) const {
|
||||
return *table_ == *x.table_ &&
|
||||
name_ == x.name_ &&
|
||||
alias_ == x.alias_ &&
|
||||
function_ == x.function_;
|
||||
}
|
||||
|
||||
column column::as(std::string a) {
|
||||
alias_ = std::move(a);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::string& column::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const std::string& column::alias() const {
|
||||
return alias_;
|
||||
}
|
||||
|
||||
utils::basic_type column::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
utils::field_attributes column::attributes() const {
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
bool column::is_function() const {
|
||||
return function_ != sql::sql_function_t::None;
|
||||
}
|
||||
|
||||
bool column::is_nullable() const {
|
||||
return !utils::is_constraint_set(attributes_.options(), utils::constraints::NotNull);
|
||||
}
|
||||
|
||||
sql::sql_function_t column::function() const {
|
||||
return function_;
|
||||
}
|
||||
|
||||
bool column::has_alias() const {
|
||||
return !alias_.empty();
|
||||
}
|
||||
|
||||
const class table* column::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void column::table(const query::table* tab) {
|
||||
table_ = tab;
|
||||
}
|
||||
|
||||
column::operator const std::string&() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
query::table* column::default_table() {
|
||||
static query::table default_table;
|
||||
|
||||
return &default_table;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#include "matador/query/constraint.hpp"
|
||||
|
||||
#include "matador/utils/constraints.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
constraint::constraint(std::string column_name, std::string table_name, utils::constraints type)
|
||||
: column_name_(std::move(column_name))
|
||||
, table_name_(std::move(table_name))
|
||||
, type_(type) {}
|
||||
|
||||
constraint::constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column)
|
||||
: column_name_(std::move(column_name))
|
||||
, table_name_(std::move(table_name))
|
||||
, type_(type)
|
||||
, referenced_table_(std::move(referenced_table))
|
||||
, referenced_column_(std::move(referenced_column)) {}
|
||||
|
||||
std::string constraint::column_name() const {
|
||||
return column_name_;
|
||||
}
|
||||
|
||||
std::string constraint::table_name() const {
|
||||
return table_name_;
|
||||
}
|
||||
|
||||
const utils::constraints& constraint::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool constraint::is_primary_key_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::PrimaryKey);
|
||||
}
|
||||
|
||||
bool constraint::is_foreign_key_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::ForeignKey);
|
||||
}
|
||||
|
||||
bool constraint::is_unique_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::Unique);
|
||||
}
|
||||
|
||||
const std::string& constraint::referenced_table() const {
|
||||
return referenced_table_;
|
||||
}
|
||||
|
||||
const std::string& constraint::referenced_column() const {
|
||||
return referenced_column_;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#include "matador/query/criteria/abstract_column_criteria.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
abstract_column_criteria::abstract_column_criteria(column col)
|
||||
: column_(std::move(col)) {}
|
||||
abstract_column_criteria::abstract_column_criteria(const table_column& col)
|
||||
: column_(col) {}
|
||||
|
||||
const column& abstract_column_criteria::col() const {
|
||||
const table_column& abstract_column_criteria::col() const {
|
||||
return column_;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
|
||||
namespace matador::query{
|
||||
between_criteria::between_criteria(column col, const int64_t min, const int64_t max)
|
||||
: abstract_column_criteria(std::move(col))
|
||||
between_criteria::between_criteria(const table_column& col, const int64_t min, const int64_t max)
|
||||
: abstract_column_criteria(col)
|
||||
, min_(utils::value{min})
|
||||
, max_(utils::value{max})
|
||||
{}
|
||||
|
||||
between_criteria::between_criteria(column col, utils::placeholder min, utils::placeholder max)
|
||||
: abstract_column_criteria(std::move(col))
|
||||
between_criteria::between_criteria(const table_column& col, utils::placeholder min, utils::placeholder max)
|
||||
: abstract_column_criteria(col)
|
||||
, min_(min)
|
||||
, max_(max)
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
binary_criteria::binary_criteria(column col, const binary_operator operand, criteria_value value)
|
||||
: abstract_column_criteria(std::move(col))
|
||||
binary_criteria::binary_criteria(const table_column& col, const binary_operator operand, criteria_value value)
|
||||
: abstract_column_criteria(col)
|
||||
, operator_(operand)
|
||||
, value_(std::move(value))
|
||||
{}
|
||||
|
|
@ -21,16 +21,16 @@ const criteria_value& binary_criteria::value() const {
|
|||
return value_;
|
||||
}
|
||||
|
||||
binary_column_criteria::binary_column_criteria(column left_column, binary_operator operand, column right_column)
|
||||
: left_column_(std::move(left_column))
|
||||
binary_column_criteria::binary_column_criteria(const table_column& left_column, const binary_operator operand, const table_column& right_column)
|
||||
: left_column_(left_column)
|
||||
, operator_(operand)
|
||||
, right_column_(std::move(right_column)){}
|
||||
, right_column_(right_column){}
|
||||
|
||||
void binary_column_criteria::accept(criteria_visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const column& binary_column_criteria::left_column() const {
|
||||
const table_column& binary_column_criteria::left_column() const {
|
||||
return left_column_;
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ binary_operator binary_column_criteria::operand() const {
|
|||
return operator_;
|
||||
}
|
||||
|
||||
const column& binary_column_criteria::right_column() const {
|
||||
const table_column& binary_column_criteria::right_column() const {
|
||||
return right_column_;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#include "matador/query/criteria/collection_criteria.hpp"
|
||||
|
||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
collection_criteria::collection_criteria(column col, const collection_operator operand_, std::vector<criteria_value> values )
|
||||
: abstract_column_criteria(std::move(col))
|
||||
collection_criteria::collection_criteria(const table_column& col, const collection_operator operand_, std::vector<criteria_value> values )
|
||||
: abstract_column_criteria(col)
|
||||
, operand_(operand_)
|
||||
, values_(std::move(values))
|
||||
{}
|
||||
|
||||
collection_criteria::collection_criteria(column col, const collection_operator operand_, const std::initializer_list<criteria_value> values )
|
||||
: abstract_column_criteria(std::move(col))
|
||||
collection_criteria::collection_criteria(const table_column& col, const collection_operator operand_, const std::initializer_list<criteria_value> values )
|
||||
: abstract_column_criteria(col)
|
||||
, operand_(operand_)
|
||||
, values_(values)
|
||||
{}
|
||||
|
|
@ -27,8 +28,8 @@ const std::vector<criteria_value>& collection_criteria::values() const {
|
|||
return values_;
|
||||
}
|
||||
|
||||
collection_query_criteria::collection_query_criteria(column col, collection_operator operand_, sql::query_context ctx)
|
||||
: abstract_column_criteria(std::move(col))
|
||||
collection_query_criteria::collection_query_criteria(const table_column& col, collection_operator operand_, sql::query_context ctx)
|
||||
: abstract_column_criteria(col)
|
||||
, operand_(operand_)
|
||||
, query_context_(std::move(ctx)){
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,51 +6,51 @@
|
|||
#include "matador/query/criteria/not_criteria.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
criteria_ptr operator==(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator==(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator!=(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator!=(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator>(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator>(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator>=(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator>=(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN_OR_EQUAL, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator<(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator<(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator<=(const column &col, utils::placeholder p) {
|
||||
criteria_ptr operator<=(const table_column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN_OR_EQUAL, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator==( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator==( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::EQUALS, col_right);
|
||||
}
|
||||
|
||||
criteria_ptr operator!=( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator!=( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::NOT_EQUALS, col_right);
|
||||
}
|
||||
|
||||
criteria_ptr operator>( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator>( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::GREATER_THAN, col_right);
|
||||
}
|
||||
|
||||
criteria_ptr operator>=( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator>=( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::GREATER_THAN_OR_EQUAL, col_right);
|
||||
}
|
||||
|
||||
criteria_ptr operator<( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator<( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::LESS_THAN, col_right);
|
||||
}
|
||||
|
||||
criteria_ptr operator<=( const column& col_left, const column& col_right ) {
|
||||
criteria_ptr operator<=( const table_column& col_left, const table_column& col_right ) {
|
||||
return std::make_unique<binary_column_criteria>(col_left, binary_operator::LESS_THAN_OR_EQUAL, col_right);
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ criteria_ptr operator!(criteria_ptr clause) {
|
|||
}
|
||||
|
||||
template <>
|
||||
criteria_ptr in(const column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
criteria_ptr in(const table_column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(arg);
|
||||
|
|
@ -75,12 +75,12 @@ criteria_ptr in(const column &col, const std::initializer_list<utils::placeholde
|
|||
return std::make_unique<collection_criteria>(col, collection_operator::In, std::move(values));
|
||||
}
|
||||
|
||||
criteria_ptr in(const column &col, sql::query_context &&ctx) {
|
||||
criteria_ptr in(const table_column &col, sql::query_context &&ctx) {
|
||||
return std::make_unique<collection_query_criteria>(col, collection_operator::In, std::move(ctx));
|
||||
}
|
||||
|
||||
template <>
|
||||
criteria_ptr out(const column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
criteria_ptr out(const table_column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(arg);
|
||||
|
|
@ -88,19 +88,19 @@ criteria_ptr out(const column &col, const std::initializer_list<utils::placehold
|
|||
return std::make_unique<collection_criteria>(col, collection_operator::Out, values);
|
||||
}
|
||||
|
||||
criteria_ptr out(const column &col, sql::query_context &&ctx) {
|
||||
criteria_ptr out(const table_column &col, sql::query_context &&ctx) {
|
||||
return std::make_unique<collection_query_criteria>(col, collection_operator::In, std::move(ctx));
|
||||
}
|
||||
|
||||
criteria_ptr between(const column &col, const int64_t min, const int64_t max) {
|
||||
criteria_ptr between(const table_column &col, const int64_t min, const int64_t max) {
|
||||
return std::make_unique<between_criteria>(col, min, max);
|
||||
}
|
||||
|
||||
criteria_ptr between(const column &col, utils::placeholder min, utils::placeholder max) {
|
||||
criteria_ptr between(const table_column &col, utils::placeholder min, utils::placeholder max) {
|
||||
return std::make_unique<between_criteria>(col, min, max);
|
||||
}
|
||||
|
||||
criteria_ptr like(const column &col, const std::string &pattern) {
|
||||
criteria_ptr like(const table_column &col, const std::string &pattern) {
|
||||
return std::make_unique<like_criteria>(col, pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#include "matador/query/criteria/like_criteria.hpp"
|
||||
|
||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
like_criteria::like_criteria(column col, std::string pattern)
|
||||
: abstract_column_criteria(std::move(col))
|
||||
like_criteria::like_criteria(const table_column& col, std::string pattern)
|
||||
: abstract_column_criteria(col)
|
||||
, pattern_(std::move(pattern)){}
|
||||
|
||||
void like_criteria::accept(criteria_visitor &visitor) const {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
#include "matador/query/generator.hpp"
|
||||
|
||||
namespace matador::query::generator {
|
||||
column_generator::column_generator(const std::string& table_name, const column_generator_options options)
|
||||
: options_(options) {
|
||||
table_stack_.push(table_name.empty() ? std::make_shared<table>() : std::make_shared<table>(table_name));
|
||||
}
|
||||
|
||||
column_generator::column_generator(const schema& repo, const std::string& table_name, const column_generator_options options)
|
||||
: repo_(std::cref(repo))
|
||||
, options_(options) {
|
||||
|
|
|
|||
|
|
@ -4,27 +4,27 @@
|
|||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
executable_query query_add_foreign_key_constraint_intermediate::references( const table& tab, const std::vector<column>& columns) {
|
||||
executable_query query_add_foreign_key_constraint_intermediate::references( const table& tab, const std::vector<table_column>& columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_add_foreign_key_reference_part>(tab, columns));
|
||||
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_add_primary_key_constraint_intermediate query_add_key_constraint_intermediate::primary_key(const column& col) const {
|
||||
query_add_primary_key_constraint_intermediate query_add_key_constraint_intermediate::primary_key(const table_column& col) const {
|
||||
return primary_keys({col});
|
||||
}
|
||||
|
||||
query_add_primary_key_constraint_intermediate query_add_key_constraint_intermediate::primary_keys( const std::vector<column>& columns) const {
|
||||
query_add_primary_key_constraint_intermediate query_add_key_constraint_intermediate::primary_keys( const std::vector<table_column>& columns) const {
|
||||
context_->parts.push_back(std::make_unique<internal::query_add_primary_key_constraint_part>(columns));
|
||||
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermediate::foreign_key(const column& col) const {
|
||||
query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermediate::foreign_key(const table_column& col) const {
|
||||
return foreign_keys({col});
|
||||
}
|
||||
|
||||
query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermediate::foreign_keys(const std::vector<column>& columns) const {
|
||||
query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermediate::foreign_keys(const std::vector<table_column>& columns) const {
|
||||
context_->parts.push_back(std::make_unique<internal::query_add_foreign_key_constraint_part>(columns));
|
||||
|
||||
return {context_};
|
||||
|
|
@ -32,7 +32,7 @@ query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermedi
|
|||
|
||||
executable_query query_alter_table_intermediate::add_constraint(const object::restriction &rest) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_add_constraint_part_by_constraint>(
|
||||
constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()}
|
||||
table_constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()}
|
||||
));
|
||||
|
||||
return {context_};
|
||||
|
|
@ -46,7 +46,7 @@ query_add_key_constraint_intermediate query_alter_table_intermediate::add_constr
|
|||
|
||||
executable_query query_alter_table_intermediate::drop_constraint(const object::restriction &rest) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_drop_key_constraint_part_by_constraint>(
|
||||
constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()})
|
||||
table_constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()})
|
||||
);
|
||||
return {context_};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
|
||||
#include "matador/object/object.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -26,41 +28,55 @@ executable_query query_create_table_columns_intermediate::constraints(const std:
|
|||
return this->constraints(std::list(constraints));
|
||||
}
|
||||
|
||||
executable_query query_create_table_columns_intermediate::constraints(std::initializer_list<constraint> constraints) {
|
||||
return {context_};
|
||||
executable_query query_create_table_columns_intermediate::constraints(const std::initializer_list<table_constraint> constraints) {
|
||||
return this->constraints(std::list(constraints));
|
||||
}
|
||||
|
||||
executable_query query_create_table_columns_intermediate::constraints(const std::list<constraint>& restrictions){
|
||||
executable_query query_create_table_columns_intermediate::constraints(const std::list<table_constraint>& constraints){
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_constraints_part>(constraints));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
executable_query query_create_table_columns_intermediate::constraints(const std::list<object::restriction>& restrictions) {
|
||||
std::list<constraint> constraints;
|
||||
for ( const auto& restr : restrictions ) {
|
||||
|
||||
std::list<table_constraint> constraints;
|
||||
for (const auto& restr : restrictions) {
|
||||
if (restr.is_primary_key_constraint()) {
|
||||
constraints.emplace_back(restr.column_name(), restr.owner()->name(), restr.attribute().attributes().options());
|
||||
} else if (restr.is_foreign_key_constraint()) {
|
||||
constraints.emplace_back(restr.column_name(), restr.owner()->name(), restr.attribute().attributes().options(), restr.ref_table_name(), restr.ref_column_name());
|
||||
} else if (restr.is_unique_constraint()) {
|
||||
constraints.emplace_back(restr.column_name(), restr.owner()->name(), restr.attribute().attributes().options());
|
||||
}
|
||||
}
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_constraints_part>(constraints));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(std::initializer_list<object::attribute> attributes) {
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::initializer_list<object::attribute> attributes) {
|
||||
return columns(std::list(attributes));
|
||||
}
|
||||
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::list<object::attribute>& attributes) {
|
||||
std::list<column> columns;
|
||||
std::list<table_column> columns;
|
||||
for (const auto& attr : attributes) {
|
||||
auto options = attr.attributes().options();
|
||||
if (!attr.is_nullable()) {
|
||||
options |= utils::constraints::NotNull;
|
||||
}
|
||||
|
||||
columns.emplace_back(nullptr, attr.name(), attr.type(), utils::field_attributes{attr.attributes().size(), options});
|
||||
}
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_columns_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(std::initializer_list<column> columns) {
|
||||
return {context_};
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(std::initializer_list<table_column> columns) {
|
||||
return this->columns(std::list(columns));
|
||||
}
|
||||
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::list<column>& columns) {
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::list<table_column>& columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_columns_part>(columns));
|
||||
|
||||
return {context_};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ query_execute_limit_intermediate query_execute_where_intermediate::limit(size_t
|
|||
return {context_};
|
||||
}
|
||||
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(const column &col) {
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<a
|
|||
return {context_};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const column &col) {
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const column &col) {
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace matador::query {
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const column &col) {
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@ query_insert_intermediate::query_insert_intermediate() {
|
|||
context_->parts.push_back(std::make_unique<internal::query_insert_part>());
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, const std::initializer_list<column> columns) {
|
||||
return into(tab, std::move(std::vector<column>{columns}));
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, const std::initializer_list<table_column> columns) {
|
||||
return into(tab, std::move(std::vector<table_column>{columns}));
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, std::vector<column> &&columns) {
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, std::vector<table_column> &&columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(tab, columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, const std::vector<std::string> &column_names) {
|
||||
std::vector<column> columns;
|
||||
std::vector<table_column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace matador::query {
|
||||
|
||||
query_select_intermediate::query_select_intermediate(const std::vector<column>& columns) {
|
||||
query_select_intermediate::query_select_intermediate(const std::vector<table_column>& columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_select_part>(columns));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
namespace matador::query {
|
||||
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const column &col) {
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const column &col) {
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ column_value_pair::column_value_pair(std::string name, utils::database_type valu
|
|||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
column_value_pair::column_value_pair(const column &col, utils::database_type value)
|
||||
column_value_pair::column_value_pair(const table_column &col, utils::database_type value)
|
||||
: column_(col)
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ column_value_pair::column_value_pair( const char* name, utils::placeholder p )
|
|||
: column_(name)
|
||||
, value_(p) {}
|
||||
|
||||
const column &column_value_pair::col() const {
|
||||
const table_column &column_value_pair::col() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const std::string& query_add_key_constraint_part::name() const {
|
|||
return name_;
|
||||
}
|
||||
|
||||
query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::constraint &co)
|
||||
query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::table_constraint &co)
|
||||
: query_part(sql::dialect_token::AddConstraint)
|
||||
, constraint_(co) {}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ void query_add_constraint_part_by_constraint::accept(query_part_visitor &visitor
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const class constraint & query_add_constraint_part_by_constraint::constraint() const {
|
||||
const table_constraint & query_add_constraint_part_by_constraint::constraint() const {
|
||||
return constraint_;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ const std::string& query_drop_key_constraint_part_by_name::name() const {
|
|||
return name_;
|
||||
}
|
||||
|
||||
query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const class constraint &co)
|
||||
query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const table_constraint &co)
|
||||
: query_part( sql::dialect_token::DropConstraint )
|
||||
, constraint_(co) {}
|
||||
|
||||
|
|
@ -66,11 +66,11 @@ void query_drop_key_constraint_part_by_constraint::accept(query_part_visitor& vi
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const class constraint& query_drop_key_constraint_part_by_constraint::constraint() const {
|
||||
const table_constraint& query_drop_key_constraint_part_by_constraint::constraint() const {
|
||||
return constraint_;
|
||||
}
|
||||
|
||||
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<column>& columns)
|
||||
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<table_column>& columns)
|
||||
: query_part(sql::dialect_token::ForeignKey)
|
||||
, columns_(columns) {}
|
||||
|
||||
|
|
@ -78,11 +78,11 @@ void query_add_foreign_key_constraint_part::accept( query_part_visitor& visitor
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<column>& query_add_foreign_key_constraint_part::columns() const {
|
||||
const std::vector<table_column>& query_add_foreign_key_constraint_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_add_foreign_key_reference_part::query_add_foreign_key_reference_part(class table tab, const std::vector<column>& columns)
|
||||
query_add_foreign_key_reference_part::query_add_foreign_key_reference_part(class table tab, const std::vector<table_column>& columns)
|
||||
: query_part(sql::dialect_token::References)
|
||||
, table_(std::move(tab))
|
||||
, columns_(columns) {}
|
||||
|
|
@ -95,11 +95,11 @@ const table& query_add_foreign_key_reference_part::table() const {
|
|||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<column>& query_add_foreign_key_reference_part::columns() const {
|
||||
const std::vector<table_column>& query_add_foreign_key_reference_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_add_primary_key_constraint_part::query_add_primary_key_constraint_part(const std::vector<column>& columns)
|
||||
query_add_primary_key_constraint_part::query_add_primary_key_constraint_part(const std::vector<table_column>& columns)
|
||||
: query_part(sql::dialect_token::PrimaryKey)
|
||||
, columns_(columns) {}
|
||||
|
||||
|
|
@ -107,11 +107,11 @@ void query_add_primary_key_constraint_part::accept( query_part_visitor& visitor
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<column>& query_add_primary_key_constraint_part::columns() const {
|
||||
const std::vector<table_column>& query_add_primary_key_constraint_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_select_part::query_select_part(std::vector<column> columns)
|
||||
query_select_part::query_select_part(std::vector<table_column> columns)
|
||||
: query_part(sql::dialect_token::Select)
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ void query_select_part::accept(query_part_visitor &visitor)
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<column>& query_select_part::columns() const
|
||||
const std::vector<table_column>& query_select_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
|
@ -185,12 +185,12 @@ query_table_name_part::query_table_name_part(const sql::dialect_token token, std
|
|||
: query_part(token)
|
||||
, table_name_(std::move(table_name)) {}
|
||||
|
||||
query_group_by_part::query_group_by_part(class column col)
|
||||
query_group_by_part::query_group_by_part(class table_column col)
|
||||
: query_part(sql::dialect_token::GroupBy)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const column &query_group_by_part::column() const
|
||||
const table_column &query_group_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
|
@ -200,12 +200,12 @@ void query_group_by_part::accept(query_part_visitor &visitor)
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_part::query_order_by_part(class column col)
|
||||
query_order_by_part::query_order_by_part(class table_column col)
|
||||
: query_part(sql::dialect_token::OrderBy)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const column &query_order_by_part::column() const
|
||||
const table_column &query_order_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
|
@ -269,7 +269,7 @@ void query_insert_part::accept(query_part_visitor &visitor)
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_into_part::query_into_part(class table tab, std::vector<column> columns)
|
||||
query_into_part::query_into_part(class table tab, std::vector<table_column> columns)
|
||||
: query_part(sql::dialect_token::Insert)
|
||||
, table_(std::move(tab))
|
||||
, columns_(std::move(columns)) {}
|
||||
|
|
@ -279,7 +279,7 @@ const table &query_into_part::table() const
|
|||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<column> &query_into_part::columns() const
|
||||
const std::vector<table_column> &query_into_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
|
@ -375,11 +375,11 @@ void query_create_table_part::accept(query_part_visitor &visitor)
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_columns_part::query_create_table_columns_part(const std::list<column>& columns)
|
||||
query_create_table_columns_part::query_create_table_columns_part(const std::list<table_column>& columns)
|
||||
: query_part( sql::dialect_token::Columns )
|
||||
, columns_(columns){}
|
||||
|
||||
const std::list<column>& query_create_table_columns_part::columns() const {
|
||||
const std::list<table_column>& query_create_table_columns_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
|
|
@ -387,11 +387,11 @@ void query_create_table_columns_part::accept(query_part_visitor& visitor) {
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_constraints_part::query_create_table_constraints_part(const std::list<class constraint>& constraints)
|
||||
query_create_table_constraints_part::query_create_table_constraints_part(const std::list<class table_constraint>& constraints)
|
||||
: query_part( sql::dialect_token::Constraint )
|
||||
, constraints_(constraints) {}
|
||||
|
||||
const std::list<class constraint>& query_create_table_constraints_part::constraints() const {
|
||||
const std::list<class table_constraint>& query_create_table_constraints_part::constraints() const {
|
||||
return constraints_;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
namespace matador::query {
|
||||
|
||||
column alias(const std::string &column, const std::string &as) {
|
||||
table_column alias(const std::string &column, const std::string &as) {
|
||||
return {column, as};
|
||||
}
|
||||
|
||||
column alias(column &&col, const std::string &as) {
|
||||
table_column alias(table_column &&col, const std::string &as) {
|
||||
col.as(as);
|
||||
return std::move(col);
|
||||
return col;
|
||||
}
|
||||
|
||||
column count(const std::string &column) {
|
||||
table_column count(const std::string &column) {
|
||||
return {sql::sql_function_t::Count, column};
|
||||
}
|
||||
|
||||
column count_all() {
|
||||
table_column count_all() {
|
||||
return count("*");
|
||||
}
|
||||
|
||||
|
|
@ -32,16 +32,16 @@ query_select_intermediate query::select() {
|
|||
return query_select_intermediate{{}};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select( const std::initializer_list<column> columns) {
|
||||
return select(std::vector<column>{columns});
|
||||
query_select_intermediate query::select( const std::initializer_list<table_column> columns) {
|
||||
return select(std::vector<table_column>{columns});
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<column>& columns) {
|
||||
query_select_intermediate query::select(const std::vector<table_column>& columns) {
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<std::string> &column_names) {
|
||||
std::vector<column> columns;
|
||||
std::vector<table_column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
|
|
@ -49,7 +49,7 @@ query_select_intermediate query::select(const std::vector<std::string> &column_n
|
|||
return select(columns);
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(std::vector<column> columns, const std::initializer_list<column> additional_columns) {
|
||||
query_select_intermediate query::select(std::vector<table_column> columns, const std::initializer_list<table_column> additional_columns) {
|
||||
for (const auto &col : additional_columns) {
|
||||
columns.push_back(col);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
#include "matador/query/query_data.hpp"
|
||||
#include "matador/query/criteria_evaluator.hpp"
|
||||
#include "matador/query/query_utils.hpp"
|
||||
#include "matador/query/constraint.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_constraint.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "matador/query/internal/basic_type_to_string_visitor.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
|
@ -37,19 +37,22 @@ sql::query_context query_compiler::compile(const query_data &data,
|
|||
return {query_};
|
||||
}
|
||||
|
||||
std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const column &col) {
|
||||
if (col.is_function()) {
|
||||
ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.name());
|
||||
ctx.prototype.back().change_type(utils::basic_type::Int32);
|
||||
} else {
|
||||
ctx.prototype.emplace_back(col.name());
|
||||
}
|
||||
std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const table_column &col) {
|
||||
if (col.is_function()) {
|
||||
ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.canonical_name());
|
||||
ctx.prototype.back().change_type(utils::basic_type::Int32);
|
||||
} else {
|
||||
ctx.prototype.emplace_back(col.canonical_name());
|
||||
}
|
||||
|
||||
|
||||
if (col.table() != nullptr) {
|
||||
if (const auto it = data.tables.find(col.table()->name()); it != data.tables.end()) {
|
||||
return prepare_identifier(*d, it->second, {col.name(), col.alias()});
|
||||
return prepare_identifier(*d,{&it->second, col.name(), col.alias()});
|
||||
}
|
||||
}
|
||||
|
||||
return prepare_identifier(*d, col);
|
||||
return prepare_identifier(*d, col);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_alter_part& part) {
|
||||
|
|
@ -126,6 +129,7 @@ void query_compiler::visit(internal::query_drop_key_constraint_part_by_name& par
|
|||
}
|
||||
|
||||
void query_compiler::visit(internal::query_drop_key_constraint_part_by_constraint& part) {
|
||||
query_.sql += " " + build_drop_constraint_string(part.constraint());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_select_part &part) {
|
||||
|
|
@ -158,8 +162,7 @@ void query_compiler::visit(internal::query_from_part &part) {
|
|||
query_.sql += " " + build_table_name(part.token(), *dialect_, part.table());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_join_part &part)
|
||||
{
|
||||
void query_compiler::visit(internal::query_join_part &part) {
|
||||
query_.sql += " " + build_table_name(part.token(), *dialect_, part.table());
|
||||
}
|
||||
|
||||
|
|
@ -299,8 +302,8 @@ void query_compiler::visit(internal::query_create_part &/*create_part*/)
|
|||
query_.sql = dialect_->create();
|
||||
}
|
||||
|
||||
std::string build_create_column(const column &col, const sql::dialect &d);
|
||||
std::string build_constraint(const class constraint &cons, const sql::dialect &d);
|
||||
std::string build_create_column(const table_column &col, const sql::dialect &d);
|
||||
std::string build_constraint(const table_constraint &cons, const sql::dialect &d);
|
||||
|
||||
void query_compiler::visit(internal::query_create_table_part &part)
|
||||
{
|
||||
|
|
@ -383,7 +386,7 @@ void query_compiler::visit(internal::query_drop_table_part &part) {
|
|||
query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table_name);
|
||||
}
|
||||
|
||||
std::string build_create_column(const column &col, const sql::dialect &d) {
|
||||
std::string build_create_column(const table_column &col, const sql::dialect &d) {
|
||||
std::string result = d.prepare_identifier_string(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) + ")");
|
||||
|
|
@ -401,11 +404,11 @@ std::string build_create_column(const column &col, const sql::dialect &d) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string build_constraint(const constraint& cons, const sql::dialect& d) {
|
||||
std::string build_constraint(const table_constraint& cons, const sql::dialect& d) {
|
||||
std::string result;
|
||||
// if (!cons.name().empty()) {
|
||||
// result.append(d.constraint()).append(" ").append(cons.name()).append(" ");
|
||||
// }
|
||||
if (!cons.name().empty()) {
|
||||
result.append(d.constraint()).append(" ").append(cons.name()).append(" ");
|
||||
}
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
result
|
||||
.append(d.primary_key())
|
||||
|
|
@ -432,11 +435,11 @@ std::string build_constraint(const constraint& cons, const sql::dialect& d) {
|
|||
std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const table& t) {
|
||||
return d.token_at(token) + " " +
|
||||
(!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") +
|
||||
d.prepare_identifier_string(t.name()) +
|
||||
(t.alias().empty() ? "" : " " + d.prepare_identifier_string(t.alias()));
|
||||
d.prepare_identifier_string(t.table_name()) +
|
||||
(!t.has_alias() ? "" : " " + d.prepare_identifier_string(t.name()));
|
||||
}
|
||||
|
||||
std::string query_compiler::build_add_constraint_string(const class constraint &c) {
|
||||
std::string query_compiler::build_add_constraint_string(const table_constraint &c) const {
|
||||
std::string result = dialect_->add_constraint() + " " + build_constraint_name(c) + " ";
|
||||
if (c.is_primary_key_constraint()) {
|
||||
result.append(dialect_->primary_key()).append(" (").append(c.column_name()).append(")");
|
||||
|
|
@ -448,11 +451,11 @@ std::string query_compiler::build_add_constraint_string(const class constraint &
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string query_compiler::build_drop_constraint_string(const class constraint &c) {
|
||||
std::string query_compiler::build_drop_constraint_string(const table_constraint &c) const {
|
||||
return dialect_->drop_constraint() + " " + build_constraint_name(c);
|
||||
}
|
||||
|
||||
std::string query_compiler::build_constraint_name(const class constraint &c) {
|
||||
std::string query_compiler::build_constraint_name(const table_constraint &c) {
|
||||
if (c.is_primary_key_constraint()) {
|
||||
return "PK_" + c.table_name();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,11 @@
|
|||
#include "matador/query/table.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
std::string prepare_identifier( const sql::dialect& d, const column& col ) {
|
||||
return prepare_identifier(d, *col.table(), col);
|
||||
}
|
||||
|
||||
std::string prepare_identifier( const sql::dialect& d, const table& tab, const column& col ) {
|
||||
std::string prepare_identifier(const sql::dialect& d, const table_column& col) {
|
||||
std::string result;
|
||||
if (!col.is_function()) {
|
||||
if (!tab.name().empty()) {
|
||||
result = d.prepare_identifier_string(tab.has_alias() ? tab.alias() : tab.name()) + ".";
|
||||
if (col.table()) {
|
||||
result = d.prepare_identifier_string(col.table()->name()) + ".";
|
||||
}
|
||||
result += d.prepare_identifier_string(col.name());
|
||||
} else {
|
||||
|
|
@ -23,21 +19,17 @@ std::string prepare_identifier( const sql::dialect& d, const table& tab, const c
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string prepare_criteria(const sql::dialect& d, const column& col) {
|
||||
std::string result;
|
||||
if (!col.is_function()) {
|
||||
// if (!col.alias.empty()) {
|
||||
// result = col.alias;
|
||||
// } else {
|
||||
if (!col.table()->name().empty()) {
|
||||
result = d.prepare_identifier_string(col.table()->has_alias() ? col.table()->alias() : col.table()->name()) + ".";
|
||||
}
|
||||
result += d.prepare_identifier_string(col.name());
|
||||
// }
|
||||
} else {
|
||||
result = d.sql_function_at(col.function()) + "(" + col.name() + ")";
|
||||
std::string prepare_criteria(const sql::dialect& d, const table_column& col) {
|
||||
std::string result;
|
||||
if (!col.is_function()) {
|
||||
if (col.table()) {
|
||||
result = d.prepare_identifier_string(col.table()->name()) + ".";
|
||||
}
|
||||
result += d.prepare_identifier_string(col.name());
|
||||
} else {
|
||||
result = d.sql_function_at(col.function()) + "(" + col.name() + ")";
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#include <utility>
|
||||
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/query/query.hpp"
|
||||
|
|
@ -7,208 +9,253 @@
|
|||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/error_code.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
schema::schema(sql::connection_pool& pool)
|
||||
: repo_(sql::backend_provider::instance().connection_dialect(pool.info().type).default_schema_name())
|
||||
, pool_(pool) {
|
||||
schema_node::schema_node(class table tab, const object::repository_node& node)
|
||||
: table_(std::move(tab))
|
||||
, node_(std::move(node)) {
|
||||
}
|
||||
|
||||
schema::schema(sql::connection_pool &pool, const std::string& name)
|
||||
: repo_(name)
|
||||
, pool_(pool) {}
|
||||
|
||||
utils::result<void, utils::error> schema::create() const {
|
||||
// Step 1: Build dependency graph
|
||||
// std::unordered_map<std::string, std::vector<std::string> > dependency_graph;
|
||||
// std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree;
|
||||
//
|
||||
// for (const auto &node: repo_) {
|
||||
// for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
|
||||
// dependency_graph[node->name()].push_back(it->second->node().name());
|
||||
//
|
||||
// if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) {
|
||||
// in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr());
|
||||
// } else {
|
||||
// in_degree[it->second->node().name()].first++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Ensure the current node exists in the graph representation
|
||||
// if (in_degree.find(node->name()) == in_degree.end()) {
|
||||
// in_degree[node->name()] = std::make_pair(0, node);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (const auto &it : dependency_graph) {
|
||||
// std::cout << "Dependency graph " << it.first << std::endl;
|
||||
// for (const auto &neighbor: it.second) {
|
||||
// std::cout << " " << neighbor << std::endl;
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// }
|
||||
|
||||
std::vector<std::string> fk_sql_commands;
|
||||
const auto c = pool_.acquire();
|
||||
|
||||
const auto q = query::query::create().schema( repo_.name() ).compile( *c );
|
||||
std::cout << q.sql << std::endl;
|
||||
|
||||
// create plain tables without constraints
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::create()
|
||||
.table(node->name())
|
||||
.columns(node->info().attributes())
|
||||
// .constraints(node->info().constraints())
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
// create primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
// create table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
return utils::ok<void>();
|
||||
const std::string & schema_node::name() const {
|
||||
return table_.name();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> schema::drop() const {
|
||||
auto c = pool_.acquire();
|
||||
// drop table primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.drop_constraint(cons)
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto& cons : node->info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.drop_constraint(cons)
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop table
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::drop()
|
||||
.table(node->name())
|
||||
.compile(*c);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = c->execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
const table &schema_node::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> schema::drop_table(const std::string& table_name) const {
|
||||
const auto c = pool_.acquire();
|
||||
auto result = query::query::drop()
|
||||
.table(table_name)
|
||||
.execute(*c);
|
||||
if (result.is_error()) {
|
||||
const object::repository_node& schema_node::node() const {
|
||||
return node_;
|
||||
}
|
||||
|
||||
schema::schema(const std::string &name)
|
||||
: repo_(name) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
|
||||
// Step 1: Build dependency graph
|
||||
// std::unordered_map<std::string, std::vector<std::string> > dependency_graph;
|
||||
// std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree;
|
||||
//
|
||||
// for (const auto &node: repo_) {
|
||||
// for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
|
||||
// dependency_graph[node->name()].push_back(it->second->node().name());
|
||||
//
|
||||
// if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) {
|
||||
// in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr());
|
||||
// } else {
|
||||
// in_degree[it->second->node().name()].first++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Ensure the current node exists in the graph representation
|
||||
// if (in_degree.find(node->name()) == in_degree.end()) {
|
||||
// in_degree[node->name()] = std::make_pair(0, node);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (const auto &it : dependency_graph) {
|
||||
// std::cout << "Dependency graph " << it.first << std::endl;
|
||||
// for (const auto &neighbor: it.second) {
|
||||
// std::cout << " " << neighbor << std::endl;
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// }
|
||||
|
||||
std::vector<std::string> fk_sql_commands;
|
||||
|
||||
const auto q = query::query::create().schema(repo_.name()).compile(conn);
|
||||
std::cout << q.sql << std::endl;
|
||||
|
||||
// create plain tables without constraints
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::create()
|
||||
.table(node->name())
|
||||
.columns(node->info().attributes())
|
||||
// .constraints(node->info().constraints())
|
||||
.compile(conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
// create primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons, conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
// create table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons, conn);
|
||||
|
||||
return utils::ok<void>();
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<std::vector<object::attribute>, utils::error> schema::describe_table(const std::string& table_name) const {
|
||||
const auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
utils::result<void, utils::error> schema::drop(const sql::connection &conn) const {
|
||||
// drop table primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.drop_constraint(cons)
|
||||
.compile(conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
return utils::ok(c->describe(table_name).release());
|
||||
}
|
||||
|
||||
// drop table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.drop_constraint(cons)
|
||||
.compile(conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop table
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::drop()
|
||||
.table(node->name())
|
||||
.compile(conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> schema::table_exists(const std::string& table_name) const {
|
||||
const auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
}
|
||||
return c->exists(repo_.name(), table_name);
|
||||
utils::result<void, utils::error> schema::drop_table(const std::string &table_name, const sql::connection &conn) const {
|
||||
auto result = query::query::drop()
|
||||
.table(table_name)
|
||||
.execute(conn);
|
||||
if (result.is_error()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
sql::query_context schema::build_add_constraint_context( const object::repository_node& node, const object::restriction& cons ) const {
|
||||
utils::result<std::vector<object::attribute>, utils::error>
|
||||
schema::describe_table(const std::string &table_name, const sql::connection &conn) const {
|
||||
// if (!conn.valid()) {
|
||||
// return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
// }
|
||||
return utils::ok(conn.describe(table_name).release());
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> schema::table_exists(const std::string &table_name, const sql::connection &conn) const {
|
||||
// if (!c.valid()) {
|
||||
// return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
// }
|
||||
return conn.exists(repo_.name(), table_name);
|
||||
}
|
||||
|
||||
schema::iterator schema::begin() {
|
||||
return schema_nodes_.begin();
|
||||
}
|
||||
|
||||
schema::iterator schema::end() {
|
||||
return schema_nodes_.end();
|
||||
}
|
||||
|
||||
schema::const_iterator schema::begin() const {
|
||||
return schema_nodes_.begin();
|
||||
}
|
||||
|
||||
schema::const_iterator schema::end() const {
|
||||
return schema_nodes_.end();
|
||||
}
|
||||
|
||||
schema::iterator schema::find(const std::string &name) {
|
||||
const auto result = repo_.basic_info(name);
|
||||
if (!result) {
|
||||
return schema_nodes_.end();
|
||||
}
|
||||
|
||||
return schema_nodes_.find(result->get().type_index());
|
||||
}
|
||||
|
||||
schema::const_iterator schema::find(const std::string &name) const {
|
||||
const auto result = repo_.basic_info(name);
|
||||
if (!result) {
|
||||
return schema_nodes_.end();
|
||||
}
|
||||
|
||||
return schema_nodes_.find(result->get().type_index());
|
||||
}
|
||||
|
||||
sql::query_context schema::build_add_constraint_context(const object::repository_node &node,
|
||||
const object::restriction &cons,
|
||||
const sql::connection &conn) const {
|
||||
if (cons.is_foreign_key_constraint()) {
|
||||
return query::query::alter()
|
||||
.table(node.name())
|
||||
.add_constraint(cons)
|
||||
.compile(*pool_.acquire());
|
||||
.table(node.name())
|
||||
.add_constraint(cons)
|
||||
.compile(conn);
|
||||
}
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
return query::query::alter()
|
||||
.table(node.name())
|
||||
.add_constraint(cons)
|
||||
.compile(*pool_.acquire());
|
||||
return query::query::alter()
|
||||
.table(node.name())
|
||||
.add_constraint(cons)
|
||||
.compile(conn);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
sql::query_context schema::build_drop_constraint_context( const object::repository_node& node, const object::restriction& cons ) const {
|
||||
sql::query_context schema::build_drop_constraint_context(const object::repository_node &node,
|
||||
const object::restriction &cons,
|
||||
const sql::connection &conn) const {
|
||||
return query::query::alter()
|
||||
.table(node.name())
|
||||
.drop_constraint(cons)
|
||||
.compile(*pool_.acquire());
|
||||
.table(node.name())
|
||||
.drop_constraint(cons)
|
||||
.compile(conn);
|
||||
}
|
||||
|
||||
void schema::insert_table(const std::type_index& ti, const object::repository_node& node) {
|
||||
std::vector<column> columns;
|
||||
for (const auto &attr : node.info().attributes()) {
|
||||
void schema::insert_table(const std::type_index &ti, const object::repository_node &node) {
|
||||
std::vector<table_column> columns;
|
||||
for (const auto &attr: node.info().attributes()) {
|
||||
columns.emplace_back(nullptr, attr.name(), attr.type(), attr.attributes());
|
||||
}
|
||||
std::ignore = tables_.insert({ti, table(node.name(), "", columns)}).first;
|
||||
std::ignore = schema_nodes_.insert({ti, schema_node{table(node.name(), columns), node}}).first;
|
||||
}
|
||||
} // namespace matador::query
|
||||
} // namespace matador::query
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include <utility>
|
||||
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
|
@ -6,57 +8,103 @@ table::table(const char* name)
|
|||
: table(std::string(name))
|
||||
{}
|
||||
|
||||
table::table(std::string name)
|
||||
: name_(std::move(name))
|
||||
{}
|
||||
table::table(const std::string& name)
|
||||
: table(name, name, {}) {}
|
||||
|
||||
table::table(std::string name, std::string as)
|
||||
: name_(std::move(name))
|
||||
, alias_(std::move(as))
|
||||
{}
|
||||
table::table(const std::string& name, const std::vector<table_column> &columns)
|
||||
: table(name, name, columns) {
|
||||
}
|
||||
|
||||
table::table( std::string name, std::string as, const std::vector<query::column>& columns )
|
||||
table::table(std::string name, std::string alias, const std::vector<table_column> &columns)
|
||||
: name_(std::move(name))
|
||||
, alias_(std::move(as))
|
||||
, alias_(std::move(alias))
|
||||
, columns_(columns) {
|
||||
for (auto& col : columns_) {
|
||||
col.table_ = this;
|
||||
for (auto &col : columns_) {
|
||||
col.table(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool table::operator==( const table& x ) const {
|
||||
return name_ == x.name_;
|
||||
table::table(const table &other)
|
||||
: table(other.name_, other.alias_, other.columns_) {
|
||||
for (auto &col : columns_) {
|
||||
col.table(this);
|
||||
}
|
||||
}
|
||||
|
||||
table table::as(const std::string &a) {
|
||||
alias_ = a;
|
||||
table & table::operator=(const table &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
return *this = table(other);
|
||||
}
|
||||
|
||||
table::table(table &&other) noexcept {
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
table & table::operator=(table &&other) noexcept {
|
||||
name_ = std::move(other.name_);
|
||||
alias_ = std::move(other.alias_);
|
||||
columns_ = std::move(other.columns_);
|
||||
for (auto &col : columns_) {
|
||||
col.table(this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
table table::as(const std::string &a) const {
|
||||
return { name_, a, columns_ };
|
||||
bool table::operator==(const table& x) const {
|
||||
return name_ == x.name_ && alias_ == x.alias_;
|
||||
}
|
||||
|
||||
bool table::has_alias() const {
|
||||
return !alias_.empty();
|
||||
table table::as(const std::string &alias) const {
|
||||
return { name_, alias, columns_ };
|
||||
}
|
||||
|
||||
const std::string& table::name() const {
|
||||
const std::string & table::table_name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const std::string& table::alias() const {
|
||||
const std::string& table::name() const {
|
||||
return alias_;
|
||||
}
|
||||
|
||||
const std::vector<column>& table::columns() const {
|
||||
const std::vector<table_column>& table::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
table::operator const std::vector<query::column>&() const {
|
||||
bool table::has_alias() const {
|
||||
return name_ != alias_;
|
||||
}
|
||||
|
||||
table::operator const std::vector<query::table_column>&() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
const table_column* table::operator[](const std::string &column_name) const {
|
||||
for (const auto &col : columns_) {
|
||||
if (col.name() == column_name) {
|
||||
return &col;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const table_column * table::column_by_name(const table &tab, const std::string &column_name) {
|
||||
for (const auto &col : tab.columns_) {
|
||||
if (col.name() == column_name) {
|
||||
return &col;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const table_column& table::create_column(class table &tab, const std::string &name) {
|
||||
tab.columns_.emplace_back(name);
|
||||
tab.columns_.back().table(&tab);
|
||||
return tab.columns_.back();
|
||||
}
|
||||
|
||||
|
||||
table operator ""_tab(const char *name, size_t len) {
|
||||
return {{name, len}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "matador/query/table.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
table_column operator ""_col(const char *name, const size_t len) {
|
||||
const std::string str(name, len);
|
||||
const auto pos = str.find('.');
|
||||
if (pos == std::string::npos) {
|
||||
return table_column{str};
|
||||
}
|
||||
|
||||
if (str.find('.', pos + 1) != std::string::npos) {
|
||||
throw std::invalid_argument("Invalid column name: multiple dots found");
|
||||
}
|
||||
|
||||
return table_column{str.substr(pos + 1)};
|
||||
}
|
||||
|
||||
table_column::table_column(const char *name)
|
||||
: table_column(std::string(name))
|
||||
{}
|
||||
|
||||
table_column::table_column(std::string name)
|
||||
: name_(std::move(name)) {}
|
||||
table_column::table_column(std::string name, std::string alias)
|
||||
: name_(std::move(name))
|
||||
, alias_(std::move(alias)) {}
|
||||
|
||||
table_column::table_column(const sql::sql_function_t func, std::string name)
|
||||
: name_(std::move(name))
|
||||
, function_(func) {}
|
||||
|
||||
table_column::table_column(const class table* tab, std::string name)
|
||||
: table_(tab)
|
||||
, name_(std::move(name)) {}
|
||||
|
||||
table_column::table_column(const class table* tab, std::string name, std::string alias)
|
||||
: table_(tab)
|
||||
, name_(std::move(name))
|
||||
, alias_(std::move(alias)) {}
|
||||
table_column::table_column(const class table* tab,
|
||||
std::string name,
|
||||
const utils::basic_type type,
|
||||
const utils::field_attributes& attributes)
|
||||
: table_(tab)
|
||||
, name_(std::move(name))
|
||||
, type_(type)
|
||||
, attributes_(attributes) {}
|
||||
|
||||
table_column::table_column(const class table* tab,
|
||||
std::string name,
|
||||
std::string alias,
|
||||
utils::basic_type type,
|
||||
const utils::field_attributes &attributes,
|
||||
const sql::sql_function_t func)
|
||||
: table_(tab)
|
||||
, name_(std::move(name))
|
||||
, alias_(std::move(alias))
|
||||
, type_(type)
|
||||
, attributes_(attributes)
|
||||
, function_(func) {}
|
||||
|
||||
table_column & table_column::operator=(const table_column &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
table_ = other.table_;
|
||||
name_ = other.name_;
|
||||
alias_ = other.alias_;
|
||||
type_ = other.type_;
|
||||
attributes_ = other.attributes_;
|
||||
function_ = other.function_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool table_column::equals(const table_column &x) const {
|
||||
if (table_ != nullptr && x.table_ != nullptr) {
|
||||
return *table_ == *x.table_ &&
|
||||
name_ == x.name_ &&
|
||||
alias_ == x.alias_ &&
|
||||
function_ == x.function_;
|
||||
}
|
||||
|
||||
return name_ == x.name_ &&
|
||||
alias_ == x.alias_ &&
|
||||
function_ == x.function_;
|
||||
}
|
||||
|
||||
table_column table_column::as(std::string a) {
|
||||
alias_ = std::move(a);
|
||||
return {table_, name_, alias_, type_, attributes_, function_};
|
||||
}
|
||||
|
||||
const std::string& table_column::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::string table_column::canonical_name() const {
|
||||
return table_ ? table_->name() + "." + name_ : name_;
|
||||
}
|
||||
|
||||
const std::string& table_column::alias() const {
|
||||
return alias_;
|
||||
}
|
||||
|
||||
utils::basic_type table_column::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
utils::field_attributes table_column::attributes() const {
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
bool table_column::is_function() const {
|
||||
return function_ != sql::sql_function_t::None;
|
||||
}
|
||||
|
||||
bool table_column::is_nullable() const {
|
||||
return !utils::is_constraint_set(attributes_.options(), utils::constraints::NotNull);
|
||||
}
|
||||
|
||||
sql::sql_function_t table_column::function() const {
|
||||
return function_;
|
||||
}
|
||||
|
||||
bool table_column::has_alias() const {
|
||||
return !alias_.empty();
|
||||
}
|
||||
|
||||
const class table* table_column::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void table_column::table(const query::table* tab) {
|
||||
table_ = tab;
|
||||
}
|
||||
|
||||
table_column::operator const std::string&() const {
|
||||
return name_;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#include "matador/query/table_constraint.hpp"
|
||||
|
||||
#include "matador/utils/constraints.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
table_constraint::table_constraint(std::string column_name, std::string table_name, utils::constraints type)
|
||||
: column_name_(std::move(column_name))
|
||||
, table_name_(std::move(table_name))
|
||||
, type_(type) {}
|
||||
|
||||
table_constraint::table_constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column)
|
||||
: column_name_(std::move(column_name))
|
||||
, table_name_(std::move(table_name))
|
||||
, type_(type)
|
||||
, referenced_table_(std::move(referenced_table))
|
||||
, referenced_column_(std::move(referenced_column)) {}
|
||||
|
||||
table_constraint::table_constraint(std::string name,
|
||||
std::string column_name,
|
||||
std::string table_name,
|
||||
utils::constraints type,
|
||||
std::string referenced_table,
|
||||
std::string referenced_column)
|
||||
: name_(std::move(name))
|
||||
, column_name_(std::move(column_name))
|
||||
, table_name_(std::move(table_name))
|
||||
, type_(type)
|
||||
, referenced_table_(std::move(referenced_table))
|
||||
, referenced_column_(std::move(referenced_column)) {}
|
||||
|
||||
std::string table_constraint::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::string table_constraint::column_name() const {
|
||||
return column_name_;
|
||||
}
|
||||
|
||||
std::string table_constraint::table_name() const {
|
||||
return table_name_;
|
||||
}
|
||||
|
||||
const utils::constraints& table_constraint::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool table_constraint::is_primary_key_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::PrimaryKey);
|
||||
}
|
||||
|
||||
bool table_constraint::is_foreign_key_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::ForeignKey);
|
||||
}
|
||||
|
||||
bool table_constraint::is_unique_constraint() const {
|
||||
return utils::is_constraint_set(type_, utils::constraints::Unique);
|
||||
}
|
||||
|
||||
const std::string& table_constraint::referenced_table() const {
|
||||
return referenced_table_;
|
||||
}
|
||||
|
||||
const std::string& table_constraint::referenced_column() const {
|
||||
return referenced_column_;
|
||||
}
|
||||
}
|
||||
|
|
@ -35,8 +35,7 @@ field &field::operator=(field &&x) noexcept {
|
|||
return *this;
|
||||
}
|
||||
|
||||
const std::string &field::name() const
|
||||
{
|
||||
const std::string &field::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
|
@ -44,59 +43,48 @@ utils::constraints field::type() const {
|
|||
return type_;
|
||||
}
|
||||
|
||||
size_t field::size() const
|
||||
{
|
||||
size_t field::size() const {
|
||||
return value_.size();
|
||||
}
|
||||
|
||||
int field::index() const
|
||||
{
|
||||
int field::index() const {
|
||||
return index_;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const field &col)
|
||||
{
|
||||
std::ostream &operator<<(std::ostream &out, const field &col) {
|
||||
out << col.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string field::str() const
|
||||
{
|
||||
std::string field::str() const {
|
||||
return as<std::string>().value_or("");
|
||||
}
|
||||
|
||||
bool field::is_integer() const
|
||||
{
|
||||
bool field::is_integer() const {
|
||||
return value_.is_integer();
|
||||
}
|
||||
|
||||
bool field::is_floating_point() const
|
||||
{
|
||||
bool field::is_floating_point() const {
|
||||
return value_.is_floating_point();
|
||||
}
|
||||
|
||||
bool field::is_bool() const
|
||||
{
|
||||
bool field::is_bool() const {
|
||||
return value_.is_bool();
|
||||
}
|
||||
|
||||
bool field::is_string() const
|
||||
{
|
||||
bool field::is_string() const {
|
||||
return value_.is_string();
|
||||
}
|
||||
|
||||
bool field::is_varchar() const
|
||||
{
|
||||
bool field::is_varchar() const {
|
||||
return value_.is_varchar();
|
||||
}
|
||||
|
||||
bool field::is_blob() const
|
||||
{
|
||||
bool field::is_blob() const {
|
||||
return value_.is_blob();
|
||||
}
|
||||
|
||||
bool field::is_null() const
|
||||
{
|
||||
bool field::is_null() const {
|
||||
return value_.is_null();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,14 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
record::record(std::initializer_list<field> columns)
|
||||
{
|
||||
record::record(const std::initializer_list<field> columns) {
|
||||
for (auto &&col :columns) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
}
|
||||
}
|
||||
|
||||
record::record(const std::vector<field> &columns)
|
||||
{
|
||||
record::record(const std::vector<field> &columns) {
|
||||
for (auto &&col :columns) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
|
|
@ -23,7 +21,6 @@ record::record(const std::vector<field> &columns)
|
|||
|
||||
record::record(const record &x)
|
||||
: fields_by_name_(x.fields_by_name_)
|
||||
//, pk_index_(x.pk_index_)
|
||||
{
|
||||
for (auto& col : x.fields_) {
|
||||
auto &it = fields_by_name_.at(col.get().name());
|
||||
|
|
@ -47,25 +44,10 @@ record &record::operator=(const record &x)
|
|||
return *this;
|
||||
}
|
||||
|
||||
const std::vector<record::field_ref> &record::columns() const
|
||||
{
|
||||
const std::vector<record::field_ref> &record::columns() const {
|
||||
return fields_;
|
||||
}
|
||||
|
||||
//bool record::has_primary_key() const
|
||||
//{
|
||||
// return pk_index_ > -1;
|
||||
//}
|
||||
//
|
||||
//std::optional<field> record::primary_key() const
|
||||
//{
|
||||
// if (!has_primary_key()) {
|
||||
// return std::nullopt;
|
||||
// }
|
||||
//
|
||||
// return columns_[pk_index_];
|
||||
//}
|
||||
|
||||
const field &record::at(const std::string &name) const {
|
||||
const auto &res = fields_by_name_.at(name);
|
||||
const auto &f = res.first;
|
||||
|
|
@ -88,8 +70,7 @@ record::const_iterator record::find(const std::string &column_name) const {
|
|||
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
||||
}
|
||||
|
||||
void record::append(const field &col)
|
||||
{
|
||||
void record::append(const field &col) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
}
|
||||
|
|
@ -140,13 +121,6 @@ void record::clear()
|
|||
fields_by_name_.clear();
|
||||
}
|
||||
|
||||
//bool record::unknown() const
|
||||
//{
|
||||
// return std::all_of(std::begin(columns_), std::end(columns_), [](const auto &col) {
|
||||
// return col.type() == data_type_t::type_unknown;
|
||||
// });
|
||||
//}
|
||||
|
||||
void record::init()
|
||||
{
|
||||
size_t index{0};
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
#include "catch2/catch_test_macros.hpp"
|
||||
#include "catch2/matchers/catch_matchers_string.hpp"
|
||||
|
||||
#include "matador/object/attribute.hpp"
|
||||
#include "matador/object/repository.hpp"
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/generator.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/string.hpp"
|
||||
|
|
@ -25,9 +23,9 @@ using namespace matador::sql;
|
|||
using namespace matador::object;
|
||||
using namespace matador::query;
|
||||
|
||||
TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][datatypes]" ) {
|
||||
TEST_CASE_METHOD(QueryFixture, "Insert and select basic datatypes", "[query][datatypes]") {
|
||||
REQUIRE(repo.attach<types>("types"));
|
||||
auto obj = object_generator::generate<types>(repo, "types");
|
||||
auto obj = object_generator::generate<types>(repo.repo(), "types");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -290,7 +288,7 @@ TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]"
|
|||
using namespace matador::sql;
|
||||
|
||||
REQUIRE(repo.attach<types>("types"));
|
||||
auto obj = object_generator::generate<types>(repo, "types");
|
||||
auto obj = object_generator::generate<types>(repo.repo(), "types");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -368,7 +366,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key", "[query][primary key]") {
|
|||
using namespace matador::sql;
|
||||
|
||||
REQUIRE(repo.attach<pk>("pk"));
|
||||
auto obj = object_generator::generate<pk>(repo, "pk");
|
||||
auto obj = object_generator::generate<pk>(repo.repo(), "pk");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -400,7 +398,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key prepared", "[query][primary key
|
|||
using namespace matador::sql;
|
||||
|
||||
REQUIRE(repo.attach<pk>("pk"));
|
||||
auto obj = object_generator::generate<pk>(repo, "pk");
|
||||
auto obj = object_generator::generate<pk>(repo.repo(), "pk");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
namespace matador::test {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
#ifndef MATADOR_QUERY_FIXTURE_HPP
|
||||
#define MATADOR_QUERY_FIXTURE_HPP
|
||||
|
||||
#include "matador/object/repository.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace matador::test {
|
||||
|
|
@ -22,7 +20,7 @@ public:
|
|||
protected:
|
||||
sql::connection db;
|
||||
std::stack <std::string> tables_to_drop;
|
||||
object::repository repo;
|
||||
query::schema repo;
|
||||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) const;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "matador/query/builder.hpp"
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "matador/utils/types.hpp"
|
||||
#include "matador/utils/string.hpp"
|
||||
|
|
@ -23,26 +24,31 @@ using namespace matador::utils;
|
|||
TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record][data types]") {
|
||||
check_table_not_exists("types");
|
||||
|
||||
const table tab("types");
|
||||
|
||||
// auto r = query::create().table(tab).columns({
|
||||
// column("id", basic_type::UInt32)
|
||||
// });
|
||||
auto res = query::create()
|
||||
.table("types")
|
||||
.table(tab)
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("val_char", basic_type::Int8),
|
||||
attribute("val_short", basic_type::Int16),
|
||||
attribute("val_int", basic_type::Int32),
|
||||
attribute("val_long_long", basic_type::Int64),
|
||||
attribute("val_uchar", basic_type::UInt8),
|
||||
attribute("val_ushort", basic_type::UInt16),
|
||||
attribute("val_uint", basic_type::UInt32),
|
||||
attribute("val_ulong_long", basic_type::UInt64),
|
||||
attribute("val_bool", basic_type::Boolean),
|
||||
attribute("val_float", basic_type::Float),
|
||||
attribute("val_double", basic_type::Double),
|
||||
attribute("val_string", basic_type::Text),
|
||||
attribute("val_varchar", basic_type::Varchar, 63),
|
||||
// attribute("val_date", basic_type::type_date),
|
||||
// attribute("val_time", basic_type::type_time),
|
||||
attribute("val_blob", basic_type::Blob),
|
||||
column("id", basic_type::UInt32),
|
||||
column("val_char", basic_type::Int8),
|
||||
column("val_short", basic_type::Int16),
|
||||
column("val_int", basic_type::Int32),
|
||||
column("val_long_long", basic_type::Int64),
|
||||
column("val_uchar", basic_type::UInt8),
|
||||
column("val_ushort", basic_type::UInt16),
|
||||
column("val_uint", basic_type::UInt32),
|
||||
column("val_ulong_long", basic_type::UInt64),
|
||||
column("val_bool", basic_type::Boolean),
|
||||
column("val_float", basic_type::Float),
|
||||
column("val_double", basic_type::Double),
|
||||
column("val_string", basic_type::Text),
|
||||
column("val_varchar", basic_type::Varchar, 63),
|
||||
// column("val_date", basic_type::type_date),
|
||||
// column("val_time", basic_type::type_time),
|
||||
column("val_blob", basic_type::Blob),
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_types").primary_key("id")
|
||||
|
|
@ -126,9 +132,9 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement", "[query][recor
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -154,9 +160,9 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement with foreign key
|
|||
auto res = query::create()
|
||||
.table("airplane")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("brand", basic_type::Varchar, 255),
|
||||
attribute("model", basic_type::Varchar, 255),
|
||||
column("id", basic_type::UInt32),
|
||||
column("brand", basic_type::Varchar, 255),
|
||||
column("model", basic_type::Varchar, 255),
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_airplane").primary_key("id"),
|
||||
|
|
@ -171,9 +177,9 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement with foreign key
|
|||
res = query::create()
|
||||
.table("flight")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("airplane_id", basic_type::UInt32),
|
||||
attribute("pilot_name", basic_type::Varchar, 255)
|
||||
column("id", basic_type::UInt32),
|
||||
column("airplane_id", basic_type::UInt32),
|
||||
column("pilot_name", basic_type::Varchar, 255)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_flight").primary_key("id"),
|
||||
|
|
@ -208,9 +214,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement", "[query][recor
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -251,9 +257,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement with foreign key
|
|||
auto res = query::create()
|
||||
.table("airplane")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("brand", basic_type::Varchar, 255),
|
||||
attribute("model", basic_type::Varchar, 255),
|
||||
column("id", basic_type::UInt32),
|
||||
column("brand", basic_type::Varchar, 255),
|
||||
column("model", basic_type::Varchar, 255),
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_airplane").primary_key("id"),
|
||||
|
|
@ -266,9 +272,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement with foreign key
|
|||
res = query::create()
|
||||
.table("flight")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("airplane_id", basic_type::UInt32),
|
||||
attribute("pilot_name", basic_type::Varchar, 255)
|
||||
column("id", basic_type::UInt32),
|
||||
column("airplane_id", basic_type::UInt32),
|
||||
column("pilot_name", basic_type::Varchar, 255)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_flight").primary_key("id"),
|
||||
|
|
@ -314,9 +320,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute update record statement", "[query][recor
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -367,9 +373,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement", "[query][record]")
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -427,9 +433,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with order by", "[query
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -473,9 +479,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -526,9 +532,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute delete statement", "[query][record]") {
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -576,8 +582,8 @@ TEST_CASE_METHOD(QueryFixture, "Test quoted identifier record", "[query][record]
|
|||
auto res = query::create()
|
||||
.table("quotes")
|
||||
.columns({
|
||||
attribute("from", basic_type::Varchar, 255),
|
||||
attribute("to", basic_type::Varchar, 255)
|
||||
column("from", basic_type::Varchar, 255),
|
||||
column("to", basic_type::Varchar, 255)
|
||||
})
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
|
|
@ -637,9 +643,9 @@ TEST_CASE_METHOD(QueryFixture, "Test create record", "[query][record][create]")
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -664,9 +670,9 @@ TEST_CASE_METHOD(QueryFixture, "Test insert record", "[query][record][insert]")
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -701,9 +707,9 @@ TEST_CASE_METHOD(QueryFixture, "Test update record", "[query][record][update]")
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -755,9 +761,9 @@ TEST_CASE_METHOD(QueryFixture, "Test prepared record statement", "[query][record
|
|||
auto stmt = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32),
|
||||
attribute("name", basic_type::Varchar, 255),
|
||||
attribute("age", basic_type::UInt16)
|
||||
column("id", basic_type::UInt32),
|
||||
column("name", basic_type::Varchar, 255),
|
||||
column("age", basic_type::UInt16)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -785,7 +791,7 @@ TEST_CASE_METHOD(QueryFixture, "Test scalar result", "[query][record][scalar][re
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", basic_type::UInt32)
|
||||
column("id", basic_type::UInt32)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "models/person.hpp"
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ using namespace matador::test;
|
|||
|
||||
TEST_CASE_METHOD(QueryFixture, "Test create statement", "[query][statement][create]") {
|
||||
REQUIRE(repo.attach<matador::test::person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -47,12 +47,12 @@ TEST_CASE_METHOD(QueryFixture, "Test insert statement", "[query][statement][inse
|
|||
using namespace matador::test;
|
||||
|
||||
REQUIRE(repo.attach<person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
REQUIRE(stmt);
|
||||
|
||||
auto res = stmt->execute();
|
||||
|
|
@ -92,12 +92,12 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda
|
|||
using namespace matador::utils;
|
||||
|
||||
REQUIRE(repo.attach<matador::test::person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
REQUIRE(stmt);
|
||||
|
||||
auto res = stmt->execute();
|
||||
|
|
@ -161,12 +161,12 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele
|
|||
using namespace matador::test;
|
||||
|
||||
REQUIRE(repo.attach<matador::test::person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
REQUIRE(stmt);
|
||||
|
||||
auto res = stmt->execute();
|
||||
|
|
@ -251,12 +251,12 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme
|
|||
using namespace matador::test;
|
||||
|
||||
REQUIRE(repo.attach<matador::test::person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto stmt = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
.constraints(obj->constraints())
|
||||
.prepare(db);
|
||||
REQUIRE(stmt);
|
||||
|
||||
auto res = stmt->execute();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
#include "matador/object/attribute.hpp"
|
||||
|
||||
#include "matador/query/builder.hpp"
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/generator.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/meta_table_macro.hpp"
|
||||
|
||||
#include "QueryFixture.hpp"
|
||||
|
||||
|
|
@ -18,12 +18,18 @@ using namespace matador::query;
|
|||
using namespace matador::sql;
|
||||
using namespace matador::test;
|
||||
|
||||
META_TABLE(recipes, RECIPE, id, name);
|
||||
META_TABLE(ingredients, INGREDIENT, id, name);
|
||||
META_TABLE(recipe_ingredients, RECIPE_INGREDIENT, recipe_id, ingredient_id);
|
||||
META_TABLE(airplanes, AIRPLANE, id, brand, model);
|
||||
META_TABLE(flights, FLIGHT, id, airplane_id, pilot_name);
|
||||
|
||||
TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") {
|
||||
auto result = repo.attach<airplane>("airplane")
|
||||
.and_then( [this] { return repo.attach<flight>("flight");} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto obj = object_generator::generate<airplane>(repo, "airplane");
|
||||
auto obj = object_generator::generate<airplane>(repo.repo(), "airplane");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -35,7 +41,7 @@ TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query
|
|||
check_table_exists("airplane");
|
||||
tables_to_drop.emplace("airplane");
|
||||
|
||||
obj = object_generator::generate<flight>(repo, "flight");
|
||||
obj = object_generator::generate<flight>(repo.repo(), "flight");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -50,7 +56,7 @@ TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query
|
|||
|
||||
TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[query][where]") {
|
||||
REQUIRE(repo.attach<person>("person"));
|
||||
const auto obj = object_generator::generate<person>(repo, "person");
|
||||
const auto obj = object_generator::generate<person>(repo.repo(), "person");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -81,13 +87,13 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[q
|
|||
|
||||
for (const auto &i: *result_record) {
|
||||
REQUIRE(i.size() == 4);
|
||||
REQUIRE(i.at(0).name() == "id");
|
||||
REQUIRE(i.at(0).name() == "person.id");
|
||||
REQUIRE(i.at(0).is_integer());
|
||||
REQUIRE(i.at(0).as<uint32_t>() == george.id);
|
||||
REQUIRE(i.at(1).name() == "name");
|
||||
REQUIRE(i.at(1).name() == "person.name");
|
||||
REQUIRE(i.at(1).is_varchar());
|
||||
REQUIRE(i.at(1).as<std::string>() == george.name);
|
||||
REQUIRE(i.at(2).name() == "age");
|
||||
REQUIRE(i.at(2).name() == "person.age");
|
||||
REQUIRE(i.at(2).is_integer());
|
||||
REQUIRE(i.at(2).as<uint32_t>() == george.age);
|
||||
}
|
||||
|
|
@ -110,9 +116,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert statement", "[query][insert]") {
|
|||
auto res = query::create()
|
||||
.table("person")
|
||||
.columns({
|
||||
attribute("id", matador::utils::basic_type::UInt32),
|
||||
attribute("name", matador::utils::basic_type::Varchar, 255),
|
||||
attribute("color", matador::utils::basic_type::Varchar, 63)
|
||||
column("id", matador::utils::basic_type::UInt32),
|
||||
column("name", matador::utils::basic_type::Varchar, 255),
|
||||
column("color", matador::utils::basic_type::Varchar, 63)
|
||||
})
|
||||
.constraints({
|
||||
constraint("PK_person").primary_key("id")
|
||||
|
|
@ -157,7 +163,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for
|
|||
.and_then( [this] { return repo.attach<flight>("flight");} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto obj = object_generator::generate<airplane>(repo, "airplane");
|
||||
auto obj = object_generator::generate<airplane>(repo.repo(), "airplane");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -169,7 +175,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for
|
|||
REQUIRE(db.exists("airplane"));
|
||||
tables_to_drop.emplace("airplane");
|
||||
|
||||
obj = object_generator::generate<flight>(repo, "flight");
|
||||
obj = object_generator::generate<flight>(repo.repo(), "flight");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -222,11 +228,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left", "[query][foreign][join_left]") {
|
||||
auto result = repo.attach<airplane>("airplane")
|
||||
.and_then( [this] { return repo.attach<flight>("flight");} );
|
||||
auto result = repo.attach<airplane>("airplanes")
|
||||
.and_then( [this] { return repo.attach<flight>("flights");} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto obj = object_generator::generate<airplane>(repo, "airplane");
|
||||
auto obj = object_generator::generate<airplane>(repo.repo(), "airplanes");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -235,10 +241,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 0);
|
||||
|
||||
REQUIRE(db.exists("airplane"));
|
||||
tables_to_drop.emplace("airplane");
|
||||
REQUIRE(db.exists("airplanes"));
|
||||
tables_to_drop.emplace("airplanes");
|
||||
|
||||
obj = object_generator::generate<flight>(repo, "flight");
|
||||
obj = object_generator::generate<flight>(repo.repo(), "flights");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -247,8 +253,8 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 0);
|
||||
|
||||
REQUIRE(db.exists("flight"));
|
||||
tables_to_drop.emplace("flight");
|
||||
REQUIRE(db.exists("flights"));
|
||||
tables_to_drop.emplace("flights");
|
||||
|
||||
std::vector planes{
|
||||
object_ptr(new airplane{1, "Airbus", "A380"}),
|
||||
|
|
@ -258,7 +264,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
|
||||
for (const auto &plane: planes) {
|
||||
res = query::insert()
|
||||
.into("airplane", generator::columns<airplane>(repo))
|
||||
.into("airplanes", generator::columns<airplane>(repo))
|
||||
.values(*plane)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
|
|
@ -266,7 +272,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
}
|
||||
|
||||
auto count = query::select({count_all()})
|
||||
.from("airplane")
|
||||
.from("airplanes")
|
||||
.fetch_value<int>(db).value();
|
||||
REQUIRE(count == 3);
|
||||
|
||||
|
|
@ -279,27 +285,31 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
|
||||
for (const auto &f: flights) {
|
||||
res = query::insert()
|
||||
.into("flight", {"id", "airplane_id", "pilot_name"})
|
||||
.into("flights", {"id", "airplane_id", "pilot_name"})
|
||||
.values(*f)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 1);
|
||||
}
|
||||
|
||||
auto f = query::select(generator::columns<flight>(repo))
|
||||
.from("flight")
|
||||
auto flight_result = query::select(generator::columns<flight>(repo))
|
||||
.from("flights")
|
||||
.fetch_one(db);
|
||||
REQUIRE(f.is_ok());
|
||||
REQUIRE(f->has_value());
|
||||
REQUIRE(f.value()->at(0).as<uint32_t>() == 4);
|
||||
REQUIRE(f.value()->at(1).as<uint32_t>() == 1);
|
||||
REQUIRE(f.value()->at(2).as<std::string>() == "hans");
|
||||
REQUIRE(flight_result.is_ok());
|
||||
REQUIRE(flight_result->has_value());
|
||||
REQUIRE(flight_result.value()->at(0).as<uint32_t>() == 4);
|
||||
REQUIRE(flight_result.value()->at(1).as<uint32_t>() == 1);
|
||||
REQUIRE(flight_result.value()->at(2).as<std::string>() == "hans");
|
||||
|
||||
auto select_result = query::select({"f.id", "ap.brand", "ap.model", "f.pilot_name"})
|
||||
.from({"flight", "f"})
|
||||
.join_left({"airplane", "ap"})
|
||||
.on("f.airplane_id"_col == "ap.id"_col)
|
||||
.order_by("f.id").asc()
|
||||
using namespace matador::query::meta;
|
||||
const auto f = FLIGHT.as("f");
|
||||
const auto ap = AIRPLANE.as("ap");
|
||||
|
||||
auto select_result = query::select({f.id, ap.brand, ap.model, f.pilot_name})
|
||||
.from(f)
|
||||
.join_left(ap)
|
||||
.on(f.airplane_id == ap.id)
|
||||
.order_by(f.id).asc()
|
||||
.fetch_all(db);
|
||||
REQUIRE(select_result.is_ok());
|
||||
|
||||
|
|
@ -318,11 +328,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single entity", "[query][join_left][find]") {
|
||||
auto result = repo.attach<airplane>("airplane")
|
||||
.and_then( [this] { return repo.attach<flight>("flight");} );
|
||||
auto result = repo.attach<airplane>("airplanes")
|
||||
.and_then( [this] { return repo.attach<flight>("flights");} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto obj = object_generator::generate<airplane>(repo, "airplane");
|
||||
auto obj = object_generator::generate<airplane>(repo.repo(), "airplanes");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -331,10 +341,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
|||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 0);
|
||||
|
||||
REQUIRE(db.exists("airplane"));
|
||||
tables_to_drop.emplace("airplane");
|
||||
REQUIRE(db.exists("airplanes"));
|
||||
tables_to_drop.emplace("airplanes");
|
||||
|
||||
obj = object_generator::generate<flight>(repo, "flight");
|
||||
obj = object_generator::generate<flight>(repo.repo(), "flights");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -343,8 +353,8 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
|||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 0);
|
||||
|
||||
REQUIRE(db.exists("flight"));
|
||||
tables_to_drop.emplace("flight");
|
||||
REQUIRE(db.exists("flights"));
|
||||
tables_to_drop.emplace("flights");
|
||||
|
||||
std::vector planes{
|
||||
object_ptr(new airplane{1, "Airbus", "A380"}),
|
||||
|
|
@ -354,7 +364,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
|||
|
||||
for (const auto &plane: planes) {
|
||||
res = query::insert()
|
||||
.into("airplane", generator::columns<airplane>(repo))
|
||||
.into("airplanes", generator::columns<airplane>(repo))
|
||||
.values(*plane)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
|
|
@ -362,7 +372,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
|||
}
|
||||
|
||||
auto count = query::select({count_all()})
|
||||
.from("airplane")
|
||||
.from("airplanes")
|
||||
.fetch_value<int>(db);
|
||||
REQUIRE(count.is_ok());
|
||||
REQUIRE(count->has_value());
|
||||
|
|
@ -377,27 +387,31 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
|||
|
||||
for (const auto &f: flights) {
|
||||
res = query::insert()
|
||||
.into("flight", generator::columns<flight>(repo))
|
||||
.into("flights", generator::columns<flight>(repo))
|
||||
.values(*f)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 1);
|
||||
}
|
||||
|
||||
auto f = query::select(generator::columns<flight>(repo))
|
||||
.from("flight")
|
||||
auto flight_result = query::select(generator::columns<flight>(repo))
|
||||
.from("flights")
|
||||
.fetch_one(db);
|
||||
REQUIRE(f.is_ok());
|
||||
REQUIRE(f->has_value());
|
||||
REQUIRE(f.value()->at(0).as<uint32_t>() == 4);
|
||||
REQUIRE(f.value()->at(1).as<uint32_t>() == 1);
|
||||
REQUIRE(f.value()->at(2).as<std::string>() == "hans");
|
||||
REQUIRE(flight_result.is_ok());
|
||||
REQUIRE(flight_result->has_value());
|
||||
REQUIRE(flight_result.value()->at(0).as<uint32_t>() == 4);
|
||||
REQUIRE(flight_result.value()->at(1).as<uint32_t>() == 1);
|
||||
REQUIRE(flight_result.value()->at(2).as<std::string>() == "hans");
|
||||
|
||||
auto select_result = query::select({"f.id", "f.airplane_id", "ap.brand", "ap.model", "f.pilot_name"})
|
||||
.from({"flight", "f"})
|
||||
.join_left({"airplane", "ap"})
|
||||
.on("f.airplane_id"_col == "ap.id"_col)
|
||||
.where("f.id"_col == 4)
|
||||
using namespace matador::query::meta;
|
||||
const auto f = FLIGHT.as("f");
|
||||
const auto ap = AIRPLANE.as("ap");
|
||||
|
||||
auto select_result = query::select({f.id, f.airplane_id, ap.brand, ap.model, f.pilot_name})
|
||||
.from(f)
|
||||
.join_left(ap)
|
||||
.on(f.airplane_id == ap.id)
|
||||
.where(f.id == 4)
|
||||
.fetch_one<flight>(db);
|
||||
|
||||
auto expected_flight = flights[0];
|
||||
|
|
@ -417,7 +431,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
auto result = repo.attach<recipe>("recipes")
|
||||
.and_then( [this] { return repo.attach<ingredient>("ingredients"); } );
|
||||
|
||||
auto obj = object_generator::generate<recipe>(repo, "recipes");
|
||||
auto obj = object_generator::generate<recipe>(repo.repo(), "recipes");
|
||||
auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -429,7 +443,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
REQUIRE(db.exists("recipes"));
|
||||
tables_to_drop.emplace("recipes");
|
||||
|
||||
obj = object_generator::generate<ingredient>(repo, "ingredients");
|
||||
obj = object_generator::generate<ingredient>(repo.repo(), "ingredients");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -441,7 +455,7 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
REQUIRE(db.exists("ingredients"));
|
||||
tables_to_drop.emplace("ingredients");
|
||||
|
||||
obj = object_generator::generate<recipe_ingredient>(repo, "recipe_ingredients");
|
||||
obj = object_generator::generate<recipe_ingredient>(repo.repo(), "recipe_ingredients");
|
||||
res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
@ -507,10 +521,16 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
REQUIRE(*res == 1);
|
||||
}
|
||||
|
||||
auto select_result = query::select({"r.id", "r.name", "ri.ingredient_id"})
|
||||
.from({"recipes", "r"})
|
||||
.join_left({"recipe_ingredients", "ri"})
|
||||
.on("r.id"_col == "ri.recipe_id"_col)
|
||||
using namespace matador::query::meta;
|
||||
|
||||
const auto r = RECIPE.as("r");
|
||||
const auto ri= RECIPE_INGREDIENT.as("ri");
|
||||
const auto i = INGREDIENT.as("i");
|
||||
|
||||
auto select_result = query::select({ r.id, r.name, ri.ingredient_id})
|
||||
.from(r)
|
||||
.join_left(ri)
|
||||
.on(r.id == ri.recipe_id)
|
||||
.fetch_all(db);
|
||||
REQUIRE(select_result.is_ok());
|
||||
|
||||
|
|
@ -525,18 +545,20 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
{9, "Fruit Salad", 3}
|
||||
};
|
||||
size_t index{0};
|
||||
for (const auto &r: *select_result) {
|
||||
REQUIRE(r.size() == 3);
|
||||
REQUIRE(r.at(0).as<uint32_t>().value() == std::get<0>(expected_result_one_join[index]));
|
||||
REQUIRE(r.at(1).as<std::string>().value() == std::get<1>(expected_result_one_join[index]));
|
||||
REQUIRE(r.at(2).as<uint32_t>().value() == std::get<2>(expected_result_one_join[index]));
|
||||
for (const auto &row: *select_result) {
|
||||
REQUIRE(row.size() == 3);
|
||||
REQUIRE(row.at(0).as<uint32_t>().value() == std::get<0>(expected_result_one_join[index]));
|
||||
REQUIRE(row.at(1).as<std::string>().value() == std::get<1>(expected_result_one_join[index]));
|
||||
REQUIRE(row.at(2).as<uint32_t>().value() == std::get<2>(expected_result_one_join[index]));
|
||||
++index;
|
||||
}
|
||||
|
||||
select_result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"})
|
||||
.from({"recipes", "r"})
|
||||
.join_left({"recipe_ingredients", "ri"}).on("r.id"_col == "ri.recipe_id"_col)
|
||||
.join_left({"ingredients", "i"}).on("ri.ingredient_id"_col == "i.id"_col)
|
||||
select_result = query::select({r.id, r.name, ri.ingredient_id, i.name})
|
||||
.from(r)
|
||||
.join_left(ri)
|
||||
.on(r.id == ri.recipe_id)
|
||||
.join_left(i)
|
||||
.on(ri.ingredient_id == i.id)
|
||||
.fetch_all(db);
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
|
|
@ -551,30 +573,32 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
{9, "Fruit Salad", 3, "Pineapple"}
|
||||
};
|
||||
index = 0;
|
||||
for (const auto &r: *select_result) {
|
||||
REQUIRE(r.size() == 4);
|
||||
REQUIRE(r.at(0).as<uint32_t>().value() == std::get<0>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(1).as<std::string>().value() == std::get<1>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(2).as<uint32_t>().value() == std::get<2>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(3).as<std::string>().value() == std::get<3>(expected_result_two_joins[index]));
|
||||
for (const auto &row: *select_result) {
|
||||
REQUIRE(row.size() == 4);
|
||||
REQUIRE(row.at(0).as<uint32_t>().value() == std::get<0>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(1).as<std::string>().value() == std::get<1>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(2).as<uint32_t>().value() == std::get<2>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(3).as<std::string>().value() == std::get<3>(expected_result_two_joins[index]));
|
||||
++index;
|
||||
}
|
||||
|
||||
select_result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"})
|
||||
.from({"recipes", "r"})
|
||||
.join_left({"recipe_ingredients", "ri"}).on("r.id"_col == "ri.recipe_id"_col)
|
||||
.join_left({"ingredients", "i"}).on("ri.ingredient_id"_col == "i.id"_col)
|
||||
.where("r.id"_col == 8)
|
||||
select_result = query::select({r.id, r.name, ri.ingredient_id, i.name})
|
||||
.from(r)
|
||||
.join_left(ri)
|
||||
.on(r.id == ri.recipe_id)
|
||||
.join_left(i)
|
||||
.on(ri.ingredient_id == i.id)
|
||||
.where(r.id == 8)
|
||||
.fetch_all(db);
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
index = 3;
|
||||
for (const auto &r: *select_result) {
|
||||
REQUIRE(r.size() == 4);
|
||||
REQUIRE(r.at(0).as<uint32_t>().value() == std::get<0>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(1).as<std::string>().value() == std::get<1>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(2).as<uint32_t>().value() == std::get<2>(expected_result_two_joins[index]));
|
||||
REQUIRE(r.at(3).as<std::string>().value() == std::get<3>(expected_result_two_joins[index]));
|
||||
for (const auto &row: *select_result) {
|
||||
REQUIRE(row.size() == 4);
|
||||
REQUIRE(row.at(0).as<uint32_t>().value() == std::get<0>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(1).as<std::string>().value() == std::get<1>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(2).as<uint32_t>().value() == std::get<2>(expected_result_two_joins[index]));
|
||||
REQUIRE(row.at(3).as<std::string>().value() == std::get<3>(expected_result_two_joins[index]));
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,46 +15,48 @@ using namespace matador::test;
|
|||
|
||||
TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema][one-to-many]") {
|
||||
using namespace matador::test;
|
||||
query::schema repo(pool/*, "NoopSchema"*/);
|
||||
query::schema repo;
|
||||
|
||||
auto result = repo.attach<department>("departments")
|
||||
.and_then([&repo] { return repo.attach<employee>("employees"); });
|
||||
REQUIRE(result);
|
||||
|
||||
result = repo.create();
|
||||
auto conn = pool.acquire();
|
||||
result = repo.create(*conn);
|
||||
REQUIRE(result);
|
||||
|
||||
auto exists_result = repo.table_exists("departments");
|
||||
auto exists_result = repo.table_exists("departments", *conn);
|
||||
REQUIRE(exists_result.is_ok());
|
||||
REQUIRE(exists_result.value());
|
||||
|
||||
result = repo.drop();
|
||||
result = repo.drop(*conn);
|
||||
REQUIRE(result);
|
||||
|
||||
exists_result = repo.table_exists("departments");
|
||||
exists_result = repo.table_exists("departments", *conn);
|
||||
REQUIRE(exists_result.is_ok());
|
||||
REQUIRE(!exists_result.value());
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SchemaFixture, "Test schema many-to-many", "[schema][many-to-many]") {
|
||||
using namespace matador::test;
|
||||
query::schema repo(pool/*, "NoopSchema"*/);
|
||||
query::schema repo;
|
||||
|
||||
auto result = repo.attach<recipe>("recipes")
|
||||
.and_then([&repo] { return repo.attach<ingredient>("ingredients"); });
|
||||
REQUIRE(result);
|
||||
|
||||
result = repo.create();
|
||||
auto conn = pool.acquire();
|
||||
result = repo.create(*conn);
|
||||
REQUIRE(result);
|
||||
|
||||
auto exists_result = repo.table_exists("recipes");
|
||||
auto exists_result = repo.table_exists("recipes", *conn);
|
||||
REQUIRE(exists_result.is_ok());
|
||||
REQUIRE(exists_result.value());
|
||||
|
||||
result = repo.drop();
|
||||
result = repo.drop(*conn);
|
||||
REQUIRE(result);
|
||||
|
||||
exists_result = repo.table_exists("recipes");
|
||||
exists_result = repo.table_exists("recipes", *conn);
|
||||
REQUIRE(exists_result.is_ok());
|
||||
REQUIRE(!exists_result.value());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
#include "SessionFixture.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
namespace matador::test {
|
||||
|
||||
SessionFixture::SessionFixture()
|
||||
: pool(connection::dns, 4)
|
||||
, ses({bus, pool}) {}
|
||||
, ses({bus, pool}, schema) {}
|
||||
|
||||
SessionFixture::~SessionFixture() {
|
||||
const auto result = ses.drop_schema();
|
||||
const auto conn = pool.acquire();
|
||||
const auto result = schema.drop(*conn);
|
||||
REQUIRE(result.is_ok());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
#include "matador/utils/message_bus.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace matador::test {
|
||||
|
|
@ -21,6 +19,8 @@ protected:
|
|||
orm::session ses;
|
||||
utils::message_bus bus;
|
||||
|
||||
query::schema schema;
|
||||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@ using namespace matador::object;
|
|||
using namespace matador::test;
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") {
|
||||
const auto result = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto result = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto plane = ses.insert<airplane>(1, "Boeing", "A380");
|
||||
|
|
@ -32,8 +35,11 @@ TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") {
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") {
|
||||
const auto res = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto res = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(res.is_ok());
|
||||
|
||||
auto result = ses.insert<airplane>(1, "Boeing", "747");
|
||||
|
|
@ -62,8 +68,11 @@ TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") {
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") {
|
||||
const auto res = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto res = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(res.is_ok());
|
||||
|
||||
auto result = ses.insert<airplane>(1, "Boeing", "747");
|
||||
|
|
@ -83,9 +92,12 @@ TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") {
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") {
|
||||
const auto result = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.attach<flight>("flights"); } )
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto result = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] { return schema.attach<flight>("flights"); } )
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto plane = ses.insert<airplane>(1, "Boeing", "A380");
|
||||
|
|
@ -105,8 +117,11 @@ TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]")
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session][find]") {
|
||||
const auto result = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto result = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
auto a380 = ses.insert<airplane>(1, "Boeing", "A380");
|
||||
|
|
@ -124,8 +139,11 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][find]") {
|
||||
const auto result = ses.attach<airplane>("airplanes")
|
||||
.and_then([this] { return ses.create_schema(); } );
|
||||
const auto result = schema.attach<airplane>("airplanes")
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
std::vector<std::unique_ptr<airplane>> planes;
|
||||
|
|
@ -157,9 +175,12 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many lazy relation", "[session][find][one-to-many][eager]") {
|
||||
auto result = ses.attach<author>("authors")
|
||||
.and_then( [this] { return ses.attach<book>("books"); } )
|
||||
.and_then( [this] { return ses.create_schema(); } );
|
||||
auto result = schema.attach<author>("authors")
|
||||
.and_then( [this] { return schema.attach<book>("books"); } )
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
|
||||
std::vector<std::unique_ptr<author>> authors;
|
||||
authors.emplace_back(new author{1, "Michael", "Crichton", "23.10.1942", 1975, true, {}});
|
||||
|
|
@ -207,9 +228,12 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many eager relation", "[session][find][one-to-many][eager]") {
|
||||
auto result = ses.attach<department>("departments")
|
||||
.and_then( [this] { return ses.attach<employee>("employees"); } )
|
||||
.and_then( [this] { return ses.create_schema(); } );
|
||||
auto result = schema.attach<department>("departments")
|
||||
.and_then( [this] { return schema.attach<employee>("employees"); } )
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
|
||||
std::vector<std::unique_ptr<department>> departments;
|
||||
departments.emplace_back(new department{1, "Insurance", {}});
|
||||
|
|
@ -260,9 +284,12 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
|||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with many-to-many eager relation", "[session][find][many-to-many][eager]") {
|
||||
auto result = ses.attach<recipe>("recipes")
|
||||
.and_then( [this] { return ses.attach<ingredient>("ingredients"); } )
|
||||
.and_then( [this] { return ses.create_schema(); } );
|
||||
auto result = schema.attach<recipe>("recipes")
|
||||
.and_then( [this] { return schema.attach<ingredient>("ingredients"); } )
|
||||
.and_then([this] {
|
||||
const auto conn = pool.acquire();
|
||||
return schema.create(*conn);
|
||||
} );
|
||||
|
||||
std::vector<std::unique_ptr<ingredient>> ingredients;
|
||||
ingredients.push_back(std::make_unique<ingredient>(1, "Apple"));
|
||||
|
|
|
|||
|
|
@ -23,18 +23,15 @@ using namespace matador::test;
|
|||
|
||||
namespace matador::test::detail {
|
||||
template<class Type, typename... Args>
|
||||
[[maybe_unused]] object_ptr<Type> make_object_ptr(Args&&... args)
|
||||
{
|
||||
[[maybe_unused]] object_ptr<Type> make_object_ptr(Args&&... args) {
|
||||
return object_ptr(new Type(std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
class StatementTestFixture : public QueryFixture
|
||||
{
|
||||
class StatementTestFixture : public QueryFixture {
|
||||
public:
|
||||
StatementTestFixture()
|
||||
{
|
||||
const auto obj = object_generator::generate<airplane>(repo, "airplane");
|
||||
StatementTestFixture() {
|
||||
const auto obj = object_generator::generate<airplane>(repo.repo(), "airplane");
|
||||
const auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class TypeTraitsTestFixture : public QueryFixture
|
|||
public:
|
||||
TypeTraitsTestFixture() {
|
||||
REQUIRE(db.open());
|
||||
const auto obj = matador::object::object_generator::generate<location>(repo, "location");
|
||||
const auto obj = matador::object::object_generator::generate<location>(repo.repo(), "location");
|
||||
const auto res = query::create()
|
||||
.table(obj->name())
|
||||
.columns(obj->attributes())
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ TEST_CASE("Generate object from type", "[object][generate]") {
|
|||
const auto obj = object::object_generator::generate<test::book>(repo, "books");
|
||||
REQUIRE(obj->name() == "books");
|
||||
REQUIRE(obj->attributes().size() == 4);
|
||||
REQUIRE(obj->constraints().size() == 2);
|
||||
REQUIRE(obj->constraints().size() == 1);
|
||||
REQUIRE(obj->has_primary_key());
|
||||
}
|
||||
|
|
@ -75,16 +75,6 @@ TEST_CASE("Test next and previous of schema node", "[schema_node][next][previous
|
|||
REQUIRE(++it == repo.end());
|
||||
}
|
||||
|
||||
TEST_CASE("Test automatic creating of a relation table with foreign key", "[schema][relation_table][foreign_key]") {
|
||||
object::repository repo;
|
||||
|
||||
REQUIRE(repo.empty());
|
||||
|
||||
auto res = repo.attach<test::department>("department");
|
||||
REQUIRE(res.is_ok());
|
||||
REQUIRE(repo.size() == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Test automatic creating of a relation table with values", "[schema][relation_table][values]") {
|
||||
object::repository repo;
|
||||
|
||||
|
|
@ -175,22 +165,13 @@ TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
|||
template<typename Type>
|
||||
class test_observer : public matador::object::observer<Type> {
|
||||
public:
|
||||
void on_attach(object::repository_node& node, const Type& prototype) override {
|
||||
int i = 0;
|
||||
}
|
||||
void on_detach(object::repository_node& node, const Type& prototype) override {
|
||||
|
||||
}
|
||||
void on_insert(Type& obj) override {
|
||||
|
||||
}
|
||||
void on_update(Type& obj) override {
|
||||
|
||||
}
|
||||
void on_delete(Type& obj) override {
|
||||
|
||||
}
|
||||
void on_attach(const object::repository_node& /*node*/, const Type& /*prototype*/) const override {}
|
||||
void on_detach(const object::repository_node& /*node*/, const Type& /*prototype*/) const override {}
|
||||
void on_insert(const Type& /*obj*/) override {}
|
||||
void on_update(const Type& /*obj*/) override {}
|
||||
void on_delete(const Type& /*obj*/) override {}
|
||||
};
|
||||
|
||||
TEST_CASE("Test repository observer", "[repository][observer]") {
|
||||
object::repository repo;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ add_executable(OrmTests
|
|||
query/QueryFixture.cpp
|
||||
query/QueryFixture.hpp
|
||||
query/QueryTest.cpp
|
||||
sql/ColumnGeneratorTest.cpp
|
||||
query/ColumnGeneratorTest.cpp
|
||||
sql/ColumnTest.cpp
|
||||
sql/ConnectionPoolFixture.hpp
|
||||
sql/ConnectionPoolTest.cpp
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
|
||||
#include "matador/query/criteria_evaluator.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/table.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/utils/macro_map.hpp"
|
||||
|
||||
#include "matador/orm/session_query_builder.hpp"
|
||||
|
||||
#include "../backend/test_connection.hpp"
|
||||
|
|
@ -39,21 +41,25 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<airplane>("airplanes")
|
||||
.and_then( [&scm] { return scm.attach<flight>("flights"); } );
|
||||
REQUIRE(result);
|
||||
|
||||
session_query_builder eqb(scm, db);
|
||||
|
||||
auto data = eqb.build<flight>("flights.id"_col == _);
|
||||
const auto it = scm.find(typeid(flight));
|
||||
REQUIRE(it != scm.end());
|
||||
const auto* col = it->second.table()["id"];
|
||||
REQUIRE(col);
|
||||
auto data = eqb.build<flight>(*col == _);
|
||||
|
||||
REQUIRE(data.is_ok());
|
||||
REQUIRE(data->root_table->name() == "flights");
|
||||
REQUIRE(data->root_table->table_name() == "flights");
|
||||
REQUIRE(data->joins.size() == 1);
|
||||
const auto flights = table("flights");
|
||||
const auto airplanes = table("airplanes");
|
||||
const std::vector<column> expected_columns {
|
||||
const auto flights = table("flights").as("t01");
|
||||
const auto airplanes = table("airplanes").as("t02");
|
||||
const std::vector<table_column> expected_columns {
|
||||
{ &flights, "id", "c01" },
|
||||
{ &airplanes, "id", "c02" },
|
||||
{ &airplanes, "brand", "c03" },
|
||||
|
|
@ -73,7 +79,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
|
|||
size_t index{0};
|
||||
criteria_evaluator evaluator(db.dialect(), qc);
|
||||
for (const auto &[join_table, condition] : data->joins) {
|
||||
REQUIRE(join_table->name() == expected_join_data[index].first);
|
||||
REQUIRE(join_table->table_name() == expected_join_data[index].first);
|
||||
REQUIRE(evaluator.evaluate(*condition) == expected_join_data[index].second);
|
||||
++index;
|
||||
}
|
||||
|
|
@ -89,21 +95,25 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<author>("authors")
|
||||
.and_then( [&scm] { return scm.attach<book>("books"); } );
|
||||
REQUIRE(result);
|
||||
|
||||
session_query_builder eqb(scm, db);
|
||||
|
||||
auto data = eqb.build<book>("books.id"_col == _);
|
||||
const auto it = scm.find(typeid(book));
|
||||
REQUIRE(it != scm.end());
|
||||
const auto* col = it->second.table()["id"];
|
||||
REQUIRE(col);
|
||||
auto data = eqb.build<book>(*col == _);
|
||||
|
||||
REQUIRE(data.is_ok());
|
||||
REQUIRE(data->root_table->name() == "books");
|
||||
REQUIRE(data->root_table->table_name() == "books");
|
||||
REQUIRE(data->joins.size() == 1);
|
||||
const auto books = table("books");
|
||||
const auto authors = table("authors");
|
||||
const std::vector<column> expected_columns {
|
||||
const auto books = table("books").as("t01");
|
||||
const auto authors = table("authors").as("t02");
|
||||
const std::vector<table_column> expected_columns {
|
||||
{ &books, "id", "c01" },
|
||||
{ &books, "title", "c02" },
|
||||
{ &authors, "id", "c03" },
|
||||
|
|
@ -127,7 +137,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
|
|||
size_t index{0};
|
||||
criteria_evaluator evaluator(db.dialect(), qc);
|
||||
for (const auto & [join_table, clause] : data->joins) {
|
||||
REQUIRE(join_table->name() == expected_join_data[index].first);
|
||||
REQUIRE(join_table->table_name() == expected_join_data[index].first);
|
||||
REQUIRE(evaluator.evaluate(*clause) == expected_join_data[index].second);
|
||||
++index;
|
||||
}
|
||||
|
|
@ -154,7 +164,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<product>("products")
|
||||
.and_then( [&scm] { return scm.attach<order_details>("order_details"); } )
|
||||
.and_then( [&scm] { return scm.attach<supplier>("suppliers"); } )
|
||||
|
|
@ -164,14 +174,18 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
|
|||
|
||||
session_query_builder eqb(scm, db);
|
||||
|
||||
auto data = eqb.build<order>("orders.order_id"_col == _);
|
||||
const auto it = scm.find(typeid(order));
|
||||
REQUIRE(it != scm.end());
|
||||
const auto* col = it->second.table()["order_id"];
|
||||
REQUIRE(col);
|
||||
auto data = eqb.build<order>(*col == _);
|
||||
|
||||
REQUIRE(data.is_ok());
|
||||
REQUIRE(data->root_table->name() == "orders");
|
||||
REQUIRE(data->root_table->table_name() == "orders");
|
||||
REQUIRE(data->joins.size() == 1);
|
||||
const auto orders = table("orders");
|
||||
const auto order_details = table("order_details");
|
||||
const std::vector<column> expected_columns = {
|
||||
const auto orders = table("orders").as("t01");
|
||||
const auto order_details = table("order_details").as("t02");
|
||||
const std::vector<table_column> expected_columns = {
|
||||
{ &orders, "order_id", "c01" },
|
||||
{ &orders, "order_date", "c02" },
|
||||
{ &orders, "required_date", "c03" },
|
||||
|
|
@ -201,7 +215,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
|
|||
size_t index{0};
|
||||
criteria_evaluator evaluator(db.dialect(), qc);
|
||||
for (const auto &jd : data->joins) {
|
||||
REQUIRE(jd.join_table->name() == expected_join_data[index].first);
|
||||
REQUIRE(jd.join_table->table_name() == expected_join_data[index].first);
|
||||
REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
|
||||
++index;
|
||||
}
|
||||
|
|
@ -217,21 +231,25 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<recipe>("recipes")
|
||||
.and_then( [&scm] { return scm.attach<ingredient>("ingredients"); } );
|
||||
REQUIRE(result);
|
||||
|
||||
session_query_builder eqb(scm, db);
|
||||
|
||||
auto data = eqb.build<ingredient>("ingredients.id"_col == _);
|
||||
const auto it = scm.find(typeid(ingredient));
|
||||
REQUIRE(it != scm.end());
|
||||
const auto* col = it->second.table()["id"];
|
||||
REQUIRE(col);
|
||||
auto data = eqb.build<ingredient>(*col == _);
|
||||
|
||||
REQUIRE(data.is_ok());
|
||||
REQUIRE(data->root_table->name() == "ingredients");
|
||||
REQUIRE(data->root_table->table_name() == "ingredients");
|
||||
REQUIRE(data->joins.size() == 2);
|
||||
const auto ingredients = table("ingredients");
|
||||
const auto recipes = table("recipes");
|
||||
const std::vector<column> expected_columns {
|
||||
const auto ingredients = table("ingredients").as("t01");
|
||||
const auto recipes = table("recipes").as("t03");
|
||||
const std::vector<table_column> expected_columns {
|
||||
{ &ingredients, "id", "c01" },
|
||||
{ &ingredients, "name", "c02" },
|
||||
{ &recipes, "id", "c03" },
|
||||
|
|
@ -251,7 +269,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
|
|||
size_t index{0};
|
||||
criteria_evaluator evaluator(db.dialect(), qc);
|
||||
for (const auto &jd : data->joins) {
|
||||
REQUIRE(jd.join_table->name() == expected_join_data[index].first);
|
||||
REQUIRE(jd.join_table->table_name() == expected_join_data[index].first);
|
||||
REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
|
||||
++index;
|
||||
}
|
||||
|
|
@ -267,21 +285,25 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<student>("students")
|
||||
.and_then( [&scm] { return scm.attach<course>("courses"); } );
|
||||
REQUIRE(result);
|
||||
|
||||
session_query_builder eqb(scm, db);
|
||||
|
||||
auto data = eqb.build<course>("courses.id"_col == _);
|
||||
const auto it = scm.find(typeid(course));
|
||||
REQUIRE(it != scm.end());
|
||||
const auto* col = it->second.table()["id"];
|
||||
REQUIRE(col);
|
||||
auto data = eqb.build<course>(*col == _);
|
||||
|
||||
REQUIRE(data.is_ok());
|
||||
REQUIRE(data->root_table->name() == "courses");
|
||||
REQUIRE(data->root_table->table_name() == "courses");
|
||||
REQUIRE(data->joins.size() == 2);
|
||||
const auto courses = table("courses");
|
||||
const auto students = table("students");
|
||||
const std::vector<column> expected_columns {
|
||||
const auto courses = table("courses").as("t01");
|
||||
const auto students = table("students").as("t03");
|
||||
const std::vector<table_column> expected_columns {
|
||||
{ &courses, "id", "c01" },
|
||||
{ &courses, "title", "c02" },
|
||||
{ &students, "id", "c03" },
|
||||
|
|
@ -301,7 +323,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
|
|||
size_t index{0};
|
||||
criteria_evaluator evaluator(db.dialect(), qc);
|
||||
for (const auto &jd : data->joins) {
|
||||
REQUIRE(jd.join_table->name() == expected_join_data[index].first);
|
||||
REQUIRE(jd.join_table->table_name() == expected_join_data[index].first);
|
||||
REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
|
||||
++index;
|
||||
}
|
||||
|
|
@ -317,7 +339,7 @@ TEST_CASE("Test eager relationship", "[session][eager]") {
|
|||
connection db("noop://noop.db");
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema scm(pool);
|
||||
schema scm;
|
||||
auto result = scm.attach<department>("departments")
|
||||
.and_then( [&scm] { return scm.attach<employee>("employees"); } );
|
||||
REQUIRE(result);
|
||||
|
|
@ -331,7 +353,7 @@ TEST_CASE("Test eager relationship", "[session][eager]") {
|
|||
.from(*data->root_table)
|
||||
.join_left(data->joins)
|
||||
.where(std::move(data->where_clause))
|
||||
.order_by(column{data->root_table.get(), data->pk_column_name})
|
||||
.order_by(table_column{data->root_table, data->pk_column_name})
|
||||
.asc()
|
||||
.str(db);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ TEST_CASE("Generate columns from object", "[column][generator]") {
|
|||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema s(pool);
|
||||
schema s;
|
||||
auto result = s.attach<product>("product");
|
||||
REQUIRE( result );
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ TEST_CASE("Generate columns for object with has many relation", "[column][genera
|
|||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema s(pool);
|
||||
schema s;
|
||||
auto result = s.attach<supplier>("supplier")
|
||||
.and_then( [&s] { return s.attach<category>("categories"); } )
|
||||
.and_then( [&s] { return s.attach<order_details>("order_details"); } )
|
||||
|
|
@ -68,7 +68,7 @@ TEST_CASE("Generate columns for object with has many relation", "[column][genera
|
|||
|
||||
const auto order_table = table("order");
|
||||
const auto order_details_table = table("order_details");
|
||||
const std::vector<column> expected_columns = {
|
||||
const std::vector<table_column> expected_columns = {
|
||||
{ &order_table, "order_id", "c01" },
|
||||
{ &order_table, "order_date", "c02" },
|
||||
{ &order_table, "required_date", "c03" },
|
||||
|
|
@ -99,14 +99,14 @@ TEST_CASE("Generate columns for object with eager foreign key relation", "[colum
|
|||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
||||
connection_pool pool("noop://noop.db", 4);
|
||||
|
||||
schema s(pool);
|
||||
schema s;
|
||||
auto result = s.attach<book>("books")
|
||||
.and_then( [&s] { return s.attach<author>("authors"); } );
|
||||
REQUIRE(result);
|
||||
|
||||
const auto books_table = table("books");
|
||||
const auto authors_table = table("authors");
|
||||
const std::vector<column> expected_columns {
|
||||
const std::vector<table_column> expected_columns {
|
||||
{ &books_table, "id", "c01" },
|
||||
{ &books_table, "title", "c02" },
|
||||
{ &authors_table, "id", "c03" },
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "matador/query/generator.hpp"
|
||||
#include "matador/query/column.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "../../models/airplane.hpp"
|
||||
#include "../../models/flight.hpp"
|
||||
|
|
@ -32,18 +32,18 @@ TEST_CASE("Test column value generator", "[generator][column_value]") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test column generator", "[generator][column]") {
|
||||
SECTION("Test column generator for simple table") {
|
||||
const std::vector expected_columns {
|
||||
column("id"),
|
||||
column("brand"),
|
||||
column("model"),
|
||||
};
|
||||
const auto result = generator::columns<airplane>();
|
||||
REQUIRE(result.size() == expected_columns.size());
|
||||
auto it = result.begin();
|
||||
for (const auto& c : expected_columns) {
|
||||
REQUIRE(c.equals( *it++));
|
||||
}
|
||||
}
|
||||
}
|
||||
// TEST_CASE("Test column generator", "[generator][column]") {
|
||||
// SECTION("Test column generator for simple table") {
|
||||
// const std::vector expected_columns {
|
||||
// column("id"),
|
||||
// column("brand"),
|
||||
// column("model"),
|
||||
// };
|
||||
// const auto result = generator::columns<airplane>();
|
||||
// REQUIRE(result.size() == expected_columns.size());
|
||||
// auto it = result.begin();
|
||||
// for (const auto& c : expected_columns) {
|
||||
// REQUIRE(c.equals( *it++));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue