// // Copyright (c) 2019-2022 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include #include #include #include #include #include #include #include #include "er_connection.hpp" #include "er_impl_common.hpp" #include "er_network_variant.hpp" #include "er_resultset.hpp" #include "er_statement.hpp" #include "get_endpoint.hpp" #include "handler_call_tracker.hpp" #include "network_result.hpp" #include "streams.hpp" using namespace boost::mysql::test; using boost::mysql::error_code; using boost::mysql::error_info; using boost::mysql::field_view; using boost::mysql::handshake_params; using boost::mysql::row; using boost::mysql::row_view; using boost::mysql::rows_view; namespace { template using impl_result_type = decltype(std::declval( )(std::declval(), std::declval())); template network_result> impl(IoObj& obj, Callable&& cb) { using R = impl_result_type; std::promise> prom; boost::asio::spawn(obj.get_executor(), [&](boost::asio::yield_context yield) { error_code ec = boost::mysql::make_error_code(boost::mysql::errc::no); error_info info("error_info not cleared properly"); R result = cb(yield[ec], info); prom.set_value(network_result(ec, std::move(info), std::move(result))); }); return prom.get_future().get(); } template class async_coroutine_resultset : public er_resultset_base { public: network_result read_one() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { return this->obj().async_read_one(info, yield); }); } network_result read_some() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { return this->obj().async_read_some(info, yield); }); } network_result read_all() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { return this->obj().async_read_all(info, yield); }); } }; template class async_coroutine_statement : public er_statement_base { public: network_result execute_params( const boost::mysql::execute_params& params, er_resultset& result ) override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { this->obj().async_execute(params, this->cast(result), info, yield); return no_result(); }); } network_result execute_collection( const std::vector& values, er_resultset& result ) override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { this->obj().async_execute(values, this->cast(result), info, yield); return no_result(); }); } network_result close() override { return impl(this->obj(), [&](boost::asio::yield_context yield, error_info& info) { this->obj().async_close(info, yield); return no_result(); }); } }; template class async_coroutine_connection : public er_connection_base { public: using er_connection_base::er_connection_base; network_result physical_connect(er_endpoint kind) override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { info.clear(); this->conn_.stream().lowest_layer().async_connect(get_endpoint(kind), yield); return no_result(); }); } network_result connect(er_endpoint kind, const handshake_params& params) override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_connect(get_endpoint(kind), params, info, yield); return no_result(); }); } network_result handshake(const handshake_params& params) override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_handshake(params, info, yield); return no_result(); }); } network_result query(boost::string_view query, er_resultset& result) override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_query(query, this->cast(result), info, yield); return no_result(); }); } network_result prepare_statement(boost::string_view statement, er_statement& stmt) override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_prepare_statement(statement, this->cast(stmt), info, yield); return no_result(); }); } network_result quit() override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_quit(info, yield); return no_result(); }); } network_result close() override { return impl(this->conn_, [&](boost::asio::yield_context yield, error_info& info) { this->conn_.async_close(info, yield); return no_result(); }); } }; template class async_coroutine_variant : public er_network_variant_base< Stream, async_coroutine_connection, async_coroutine_statement, async_coroutine_resultset> { public: const char* variant_name() const override { return "async_coroutine"; } }; async_coroutine_variant tcp; async_coroutine_variant tcp_ssl; } // namespace void boost::mysql::test::add_async_coroutine(std::vector& output) { output.push_back(&tcp); output.push_back(&tcp_ssl); }