diff --git a/demo/work.cpp b/demo/work.cpp index 7c23005..1aa3077 100644 --- a/demo/work.cpp +++ b/demo/work.cpp @@ -58,7 +58,7 @@ using namespace work::models; // the database. // schema.attach("payloads", make_polymorph("type")); // schema.attach("id_list_payloads", make_polymorph_type("IdPayload")); -// schema.attach("id_payloads"make_polymorph_type("IdListPayload")); +// schema.attach("id_payloads", make_polymorph_type("IdListPayload")); // object::object_ptr payload; // auto result = payload.as(); // if (result.is_ok()) { @@ -73,14 +73,18 @@ int main() { // logger::default_min_log_level(logger::log_level::LVL_DEBUG); // logger::add_log_sink(logger::create_stdout_sink()); - const object::schema schema("Administration"); - // sql::connection_pool pool("postgres://news:news@127.0.0.1:15432/matador", 4); sql::connection_pool pool("postgres://test:test123!@127.0.0.1:5432/matador", 4); + object::schema admin_schema("Administration"); + + auto result = admin_schema.attach("collection_centers"); + admin_schema.create(pool); + admin_schema.drop(pool); + orm::session ses(pool); - auto result = ses.attach("collection_centers") + result = ses.attach("collection_centers") .and_then([&ses] { return ses.attach("user_directories"); }) .and_then([&ses] { return ses.attach("ldap_group_schema_settings"); }) .and_then([&ses] { return ses.attach("ldap_import_settings"); }) diff --git a/include/matador/orm/query_builder_exception.hpp b/include/matador/orm/query_builder_exception.hpp index 50f527c..46e11ba 100644 --- a/include/matador/orm/query_builder_exception.hpp +++ b/include/matador/orm/query_builder_exception.hpp @@ -1,8 +1,9 @@ #ifndef QUERY_BUILDER_EXCEPTION_HPP #define QUERY_BUILDER_EXCEPTION_HPP +#include "matador/utils/error.hpp" + #include -#include namespace matador::orm { @@ -10,18 +11,20 @@ enum class query_build_error : std::uint8_t { Ok = 0, UnknownType, MissingPrimaryKey, - UnexpectedError + UnexpectedError, + QueryError }; - class query_builder_exception final : public std::exception { public: - explicit query_builder_exception(const query_build_error error) : error_(error) {} + explicit query_builder_exception(const query_build_error error, utils::error &&err = {}); - [[nodiscard]] query_build_error error() const { return error_; } + [[nodiscard]] query_build_error error_type() const; + [[nodiscard]] const utils::error &error() const; private: - const query_build_error error_; + const query_build_error error_type_; + utils::error error_; }; } diff --git a/include/matador/orm/session.hpp b/include/matador/orm/session.hpp index 6ec45a5..75affa5 100644 --- a/include/matador/orm/session.hpp +++ b/include/matador/orm/session.hpp @@ -50,10 +50,6 @@ public: 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.")); @@ -78,10 +74,6 @@ public: template utils::result, utils::error> find() { - // const 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.")); @@ -93,7 +85,13 @@ public: 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(*this); + const auto ctx = build_select_query(data.release()).compile(dialect_, query::query_mode::Prepared); + + auto result = fetch(ctx); + if (!result.is_ok()) { + return utils::failure(result.err()); + } + return utils::ok(sql::query_result(result.release(), []{ return new Type();})); } template @@ -139,7 +137,6 @@ utils::result session::attach( const std::string& 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()); diff --git a/include/matador/orm/session_query_builder.hpp b/include/matador/orm/session_query_builder.hpp index 78abd89..0cb189c 100644 --- a/include/matador/orm/session_query_builder.hpp +++ b/include/matador/orm/session_query_builder.hpp @@ -6,8 +6,8 @@ #include "matador/query/condition.hpp" #include "matador/query/query.hpp" -#include "matador/sql/connection.hpp" #include "matador/sql/executor.hpp" +#include "matador/sql/statement.hpp" #include "matador/object/join_columns_collector.hpp" #include "matador/object/schema.hpp" @@ -17,7 +17,7 @@ #include "matador/utils/value.hpp" #include -#include +#include namespace matador::orm { @@ -25,6 +25,7 @@ struct entity_query_data { std::shared_ptr root_table; std::string pk_column_name{}; std::vector columns{}; + std::unordered_map lazy_loading_statements{}; std::vector joins{}; std::unique_ptr where_clause{}; }; @@ -50,7 +51,7 @@ public: return {utils::ok(std::move(entity_query_data_))}; } catch (const query_builder_exception &ex) { - return {utils::failure(ex.error())}; + return {utils::failure(ex.error_type())}; } catch (...) { return {utils::failure(query_build_error::UnexpectedError)}; } @@ -71,7 +72,7 @@ public: return {utils::ok(std::move(entity_query_data_))}; } catch (const query_builder_exception &ex) { - return {utils::failure(ex.error())}; + return {utils::failure(ex.error_type())}; } catch (...) { return {utils::failure(query_build_error::UnexpectedError)}; } @@ -286,10 +287,15 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u using namespace matador::utils; using namespace matador::query; // create select query - const auto result = matador::query::query::select(schema_) + auto result = matador::query::query::select(schema_) .from(*foreign_table) .where(sql::column(foreign_table, id, "") == _) .prepare(executor_); + if (!result) { + throw query_builder_exception(query_build_error::QueryError, result.release_error()); + } + + entity_query_data_.lazy_loading_statements.emplace(id, std::move(result.release())); } } diff --git a/include/matador/sql/query_result.hpp b/include/matador/sql/query_result.hpp index 7a05055..e2d2282 100644 --- a/include/matador/sql/query_result.hpp +++ b/include/matador/sql/query_result.hpp @@ -129,10 +129,15 @@ public: public: explicit query_result(std::unique_ptr &&impl) - : impl_(std::move(impl)) {} + : impl_(std::move(impl)) + , creator_([this]{ return detail::create_prototype(impl_->prototype()); } ) {} + + query_result(std::unique_ptr &&impl, creator_func&& creator) + : impl_(std::move(impl)) + , creator_(std::move(creator)) {} iterator begin() { return std::move(++iterator(this)); } - iterator end() { return {}; } + static iterator end() { return {}; } private: friend class query_result_iterator; @@ -143,12 +148,14 @@ private: protected: std::unique_ptr impl_; + creator_func creator_; }; template Type *query_result::create() { - return detail::create_prototype(impl_->prototype()); + return creator_(); } + template void query_result::bind(const Type &obj) { impl_->bind(obj); diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 2abbb47..6706f7c 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -70,6 +70,7 @@ add_library(matador-orm STATIC ../../include/matador/sql/statement.hpp ../../include/matador/sql/table.hpp orm/error_code.cpp + orm/query_builder_exception.cpp orm/session.cpp orm/session_insert_builder.cpp orm/session_query_builder.cpp diff --git a/source/orm/orm/query_builder_exception.cpp b/source/orm/orm/query_builder_exception.cpp new file mode 100644 index 0000000..6edc195 --- /dev/null +++ b/source/orm/orm/query_builder_exception.cpp @@ -0,0 +1,17 @@ +#include "matador/orm/query_builder_exception.hpp" + +namespace matador::orm { + +query_builder_exception::query_builder_exception( const query_build_error error, utils::error&& err ) +: error_type_(error) +, error_( std::move(err) ) {} + +query_build_error query_builder_exception::error_type() const { + return error_type_; +} + +const utils::error& query_builder_exception::error() const { + return error_; +} + +} \ No newline at end of file