From 81d6482eb7f3eeeac40b62dcf8a95c3ed8963f33 Mon Sep 17 00:00:00 2001 From: ruben Date: Mon, 10 Feb 2020 04:26:27 +0000 Subject: [PATCH] Now network tests exercise async functions Now statement::async_execute perform adequate param checking --- TODO.txt | 3 +- include/mysql/impl/prepared_statement.ipp | 57 +++++++++++++++----- include/mysql/prepared_statement.hpp | 3 ++ test/integration/execute_statement.cpp | 12 +++++ test/integration/integration_test_common.hpp | 16 +++++- 5 files changed, 77 insertions(+), 14 deletions(-) diff --git a/TODO.txt b/TODO.txt index 4d11f139..28168b50 100644 --- a/TODO.txt +++ b/TODO.txt @@ -47,4 +47,5 @@ Technical debt Take fetch_many() algorithm out into network_algorithms (e.g. read_many_rows) Rename (De)SerializationContext Test zero dates - clear_errors() function to clear error_info and error_code at once \ No newline at end of file + clear_errors() function to clear error_info and error_code at once + Review .hpp/.ipp convention \ No newline at end of file diff --git a/include/mysql/impl/prepared_statement.ipp b/include/mysql/impl/prepared_statement.ipp index 0f677874..de6c1271 100644 --- a/include/mysql/impl/prepared_statement.ipp +++ b/include/mysql/impl/prepared_statement.ipp @@ -3,6 +3,26 @@ #include "mysql/impl/network_algorithms/execute_statement.hpp" #include "mysql/impl/stringize.hpp" +#include + +template +template +void mysql::prepared_statement::check_num_params( + ForwardIterator first, + ForwardIterator last, + error_code& err, + error_info& info +) const +{ + auto param_count = std::distance(first, last); + if (param_count != num_params()) + { + err = detail::make_error_code(Error::wrong_num_params); + info.set_message(detail::stringize( + "prepared_statement::execute: expected ", num_params(), " params, but got ", param_count)); + } +} + template template @@ -16,18 +36,13 @@ mysql::resultset mysql::prepared_statement::execute( assert(valid()); mysql::resultset res; + err.clear(); + info.clear(); - auto param_count = std::distance(params_first, params_last); - if (param_count != num_params()) + // Verify we got passed the right number of params + check_num_params(params_first, params_last, err, info); + if (!err) { - err = detail::make_error_code(Error::wrong_num_params); - info.set_message(detail::stringize( - "prepared_statement::execute: expected ", num_params(), " params, but got ", param_count)); - } - else - { - err.clear(); - info.clear(); detail::execute_statement( *channel_, stmt_msg_.statement_id.value, @@ -64,8 +79,26 @@ auto mysql::prepared_statement::async_execute( CompletionToken&& token ) const { - // TODO: actually return an error message here instead of crashing - assert(std::distance(params_first, params_last) == num_params()); + // Check we got passed the right number of params + error_code err; + error_info info; + check_num_params(params_first, params_last, err, info); + if (err) + { + using HandlerSignature = void(error_code, error_info, resultset); + boost::asio::async_completion completion (token); + return boost::asio::post( + channel_->next_layer().get_executor(), + boost::beast::bind_front_handler( + std::move(completion.completion_handler), + err, + std::move(info), + resultset() + ) + ); + } + + // Actually execute the statement return detail::async_execute_statement( *channel_, stmt_msg_.statement_id.value, diff --git a/include/mysql/prepared_statement.hpp b/include/mysql/prepared_statement.hpp index fdd00880..d162d0c8 100644 --- a/include/mysql/prepared_statement.hpp +++ b/include/mysql/prepared_statement.hpp @@ -16,6 +16,9 @@ class prepared_statement { detail::channel* channel_ {}; detail::com_stmt_prepare_ok_packet stmt_msg_; + + template + void check_num_params(ForwardIterator first, ForwardIterator last, error_code& err, error_info& info) const; public: prepared_statement() = default; prepared_statement(detail::channel& chan, const detail::com_stmt_prepare_ok_packet& msg) noexcept: diff --git a/test/integration/execute_statement.cpp b/test/integration/execute_statement.cpp index acac713a..81d5a402 100644 --- a/test/integration/execute_statement.cpp +++ b/test/integration/execute_statement.cpp @@ -33,6 +33,12 @@ struct ExecuteStatementIteratorTraits { return stmt.execute(first, last); } + + template + static auto async(const tcp_prepared_statement& stmt, listit first, listit last, CompletionToken&& token) + { + return stmt.async_execute(first, last, std::forward(token)); + } }; struct ExecuteStatementIteratorTest : public NetworkTest {}; @@ -81,6 +87,12 @@ struct ExecuteStatementContainerTraits { return stmt.execute(v); } + + template + static auto async(const tcp_prepared_statement& stmt, const std::vector& v, CompletionToken&& token) + { + return stmt.async_execute(v, std::forward(token)); + } }; struct ExecuteStatementContainerTest : public NetworkTest {}; diff --git a/test/integration/integration_test_common.hpp b/test/integration/integration_test_common.hpp index e04bc2b7..92aac754 100644 --- a/test/integration/integration_test_common.hpp +++ b/test/integration/integration_test_common.hpp @@ -241,6 +241,12 @@ public: template using traits_network_function = typename get_network_function_type::type; +template +struct printer +{ + static_assert(std::is_same_v); +}; + template auto make_network_functions_impl(R(*)(Args...)) { @@ -266,9 +272,17 @@ auto make_network_functions_impl(R(*)(Args...)) } return res; }; + auto async = [](Args... args) { + std::promise prom; + TraitsType::async(std::forward(args)..., [&prom](error_code errc, error_info info, auto retval) { + prom.set_value(NetResultType{errc, std::move(info), std::move(retval)}); + }); + return prom.get_future().get(); + }; return std::vector{ NetFunType("sync_errc", sync_errc), - NetFunType("sync_exc", sync_exc) + NetFunType("sync_exc", sync_exc), + NetFunType("async", async) }; }