#ifndef QUERY_SESSION_HPP #define QUERY_SESSION_HPP #include "matador/orm/error_code.hpp" #include "matador/orm/session_query_builder.hpp" #include "matador/query/query.hpp" #include "matador/sql/column_generator.hpp" #include "matador/sql/connection.hpp" #include "matador/sql/connection_pool.hpp" #include "matador/sql/statement.hpp" #include "matador/object/object_ptr.hpp" #include "matador/object/object_definition.hpp" #include "matador/object/schema.hpp" #include namespace matador::orm { utils::error make_error(error_code ec, const std::string &msg); class session final { public: explicit session(sql::connection_pool &pool); template [[nodiscard]] utils::result attach(const std::string &table_name) const; utils::result create_schema() const; template utils::result, utils::error> insert(Type *obj); template< class Type, typename... Args > utils::result, utils::error> insert(Args&&... args) { return insert(new Type(std::forward(args)...)); } template utils::result, utils::error> find(const PrimaryKeyType &pk) { auto c = pool_.acquire(); if (!c.valid()) { return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(pk); if (!data.is_ok()) { return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } auto obj = build_select_query(data.release()).template fetch_one(*c); if (!obj) { return utils::failure(obj.err()); } if (!obj->get()) { return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info->get().name() + " with primary key " + std::to_string(pk) + ".")); } return utils::ok(object::object_ptr{ obj->release() }); } template utils::result, utils::error> find() { auto c = pool_.acquire(); if (!c.valid()) { return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(); if (!data.is_ok()) { return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } return build_select_query(data.release()).template fetch_all(*c); } template utils::result select() { auto c = pool_.acquire(); if (!c.valid()) { return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(); if (!data.is_ok()) { return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } return utils::ok(build_select_query(data.release()).template fetch_all(*c)); } template utils::result drop_table(); utils::result drop_table(const std::string &table_name) const; [[nodiscard]] utils::result, utils::error> fetch(const sql::query_context &q) const; [[nodiscard]] size_t execute(const std::string &sql) const; [[nodiscard]] sql::statement prepare(const sql::query_context& q) const; [[nodiscard]] std::vector describe_table(const std::string &table_name) const; [[nodiscard]] bool table_exists(const std::string &table_name) const; [[nodiscard]] const sql::dialect& dialect() const; private: friend class query_select; static query::fetchable_query build_select_query(entity_query_data &&data); private: sql::connection_pool &pool_; const sql::dialect &dialect_; std::unique_ptr schema_; mutable std::unordered_map prototypes_; }; template [[nodiscard]] utils::result session::attach(const std::string &table_name) const { return schema_->attach(table_name); } template utils::result, utils::error> session::insert(Type *obj) { auto c = pool_.acquire(); auto info = schema_->info(); if (!info) { return utils::failure(info.err()); } auto res = query::query::insert() .into(info->get().name(), sql::column_generator::generate(*schema_, true)) .values(*obj) .execute(*c); if (!res) { return utils::failure(res.err()); } return utils::ok(object::object_ptr{obj}); } template utils::result session::drop_table() { auto info = schema_->info(); if (info) { return drop_table(info->get().name()); } return utils::failure(info.err()); } } #endif //QUERY_SESSION_HPP