mirror of
https://github.com/boostorg/mysql.git
synced 2026-02-13 12:32:18 +00:00
Now network tests exercise async functions
Now statement::async_execute perform adequate param checking
This commit is contained in:
3
TODO.txt
3
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
|
||||
clear_errors() function to clear error_info and error_code at once
|
||||
Review .hpp/.ipp convention
|
||||
@@ -3,6 +3,26 @@
|
||||
|
||||
#include "mysql/impl/network_algorithms/execute_statement.hpp"
|
||||
#include "mysql/impl/stringize.hpp"
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
|
||||
template <typename Stream>
|
||||
template <typename ForwardIterator>
|
||||
void mysql::prepared_statement<Stream>::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 <typename Stream>
|
||||
template <typename ForwardIterator>
|
||||
@@ -16,18 +36,13 @@ mysql::resultset<Stream> mysql::prepared_statement<Stream>::execute(
|
||||
assert(valid());
|
||||
|
||||
mysql::resultset<Stream> 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<StreamType>::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<StreamType>);
|
||||
boost::asio::async_completion<CompletionToken, HandlerSignature> 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<StreamType>()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Actually execute the statement
|
||||
return detail::async_execute_statement(
|
||||
*channel_,
|
||||
stmt_msg_.statement_id.value,
|
||||
|
||||
@@ -16,6 +16,9 @@ class prepared_statement
|
||||
{
|
||||
detail::channel<Stream>* channel_ {};
|
||||
detail::com_stmt_prepare_ok_packet stmt_msg_;
|
||||
|
||||
template <typename ForwardIterator>
|
||||
void check_num_params(ForwardIterator first, ForwardIterator last, error_code& err, error_info& info) const;
|
||||
public:
|
||||
prepared_statement() = default;
|
||||
prepared_statement(detail::channel<Stream>& chan, const detail::com_stmt_prepare_ok_packet& msg) noexcept:
|
||||
|
||||
@@ -33,6 +33,12 @@ struct ExecuteStatementIteratorTraits
|
||||
{
|
||||
return stmt.execute(first, last);
|
||||
}
|
||||
|
||||
template <typename CompletionToken>
|
||||
static auto async(const tcp_prepared_statement& stmt, listit first, listit last, CompletionToken&& token)
|
||||
{
|
||||
return stmt.async_execute(first, last, std::forward<CompletionToken>(token));
|
||||
}
|
||||
};
|
||||
|
||||
struct ExecuteStatementIteratorTest : public NetworkTest<ExecuteStatementIteratorTraits> {};
|
||||
@@ -81,6 +87,12 @@ struct ExecuteStatementContainerTraits
|
||||
{
|
||||
return stmt.execute(v);
|
||||
}
|
||||
|
||||
template <typename CompletionToken>
|
||||
static auto async(const tcp_prepared_statement& stmt, const std::vector<value>& v, CompletionToken&& token)
|
||||
{
|
||||
return stmt.async_execute(v, std::forward<CompletionToken>(token));
|
||||
}
|
||||
};
|
||||
|
||||
struct ExecuteStatementContainerTest : public NetworkTest<ExecuteStatementContainerTraits> {};
|
||||
|
||||
@@ -241,6 +241,12 @@ public:
|
||||
template <typename TraitsType>
|
||||
using traits_network_function = typename get_network_function_type<TraitsType>::type;
|
||||
|
||||
template <typename... T>
|
||||
struct printer
|
||||
{
|
||||
static_assert(std::is_same_v<T..., int>);
|
||||
};
|
||||
|
||||
template <typename TraitsType, typename R, typename... Args>
|
||||
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<NetResultType> prom;
|
||||
TraitsType::async(std::forward<Args>(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>{
|
||||
NetFunType("sync_errc", sync_errc),
|
||||
NetFunType("sync_exc", sync_exc)
|
||||
NetFunType("sync_exc", sync_exc),
|
||||
NetFunType("async", async)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user