725 lines
22 KiB
C++
725 lines
22 KiB
C++
|
//
|
||
|
// Copyright (c) 2019-2024 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)
|
||
|
//
|
||
|
|
||
|
#ifndef BOOST_MYSQL_DETAIL_CONNECTION_IMPL_HPP
|
||
|
#define BOOST_MYSQL_DETAIL_CONNECTION_IMPL_HPP
|
||
|
|
||
|
#include <boost/mysql/any_address.hpp>
|
||
|
#include <boost/mysql/connect_params.hpp>
|
||
|
#include <boost/mysql/diagnostics.hpp>
|
||
|
#include <boost/mysql/error_code.hpp>
|
||
|
#include <boost/mysql/execution_state.hpp>
|
||
|
#include <boost/mysql/field_view.hpp>
|
||
|
#include <boost/mysql/handshake_params.hpp>
|
||
|
#include <boost/mysql/metadata_mode.hpp>
|
||
|
#include <boost/mysql/rows_view.hpp>
|
||
|
#include <boost/mysql/statement.hpp>
|
||
|
#include <boost/mysql/string_view.hpp>
|
||
|
|
||
|
#include <boost/mysql/detail/access.hpp>
|
||
|
#include <boost/mysql/detail/algo_params.hpp>
|
||
|
#include <boost/mysql/detail/any_execution_request.hpp>
|
||
|
#include <boost/mysql/detail/config.hpp>
|
||
|
#include <boost/mysql/detail/connect_params_helpers.hpp>
|
||
|
#include <boost/mysql/detail/engine.hpp>
|
||
|
#include <boost/mysql/detail/execution_processor/execution_processor.hpp>
|
||
|
#include <boost/mysql/detail/writable_field_traits.hpp>
|
||
|
|
||
|
#include <boost/core/ignore_unused.hpp>
|
||
|
#include <boost/mp11/integer_sequence.hpp>
|
||
|
#include <boost/system/result.hpp>
|
||
|
|
||
|
#include <array>
|
||
|
#include <cstddef>
|
||
|
#include <cstring>
|
||
|
#include <memory>
|
||
|
#include <tuple>
|
||
|
#include <utility>
|
||
|
|
||
|
namespace boost {
|
||
|
namespace mysql {
|
||
|
|
||
|
// Forward decl
|
||
|
template <class... StaticRow>
|
||
|
class static_execution_state;
|
||
|
|
||
|
struct character_set;
|
||
|
class pipeline_request;
|
||
|
|
||
|
namespace detail {
|
||
|
|
||
|
// Forward decl
|
||
|
class connection_state;
|
||
|
|
||
|
//
|
||
|
// Helpers to interact with connection_state, without including its definition
|
||
|
//
|
||
|
struct connection_state_deleter
|
||
|
{
|
||
|
BOOST_MYSQL_DECL void operator()(connection_state*) const;
|
||
|
};
|
||
|
|
||
|
BOOST_MYSQL_DECL std::vector<field_view>& get_shared_fields(connection_state&);
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
any_resumable_ref setup(connection_state&, const AlgoParams&);
|
||
|
|
||
|
// Note: AlgoParams should have !is_void_result
|
||
|
template <class AlgoParams>
|
||
|
typename AlgoParams::result_type get_result(const connection_state&);
|
||
|
|
||
|
//
|
||
|
// execution helpers
|
||
|
//
|
||
|
template <class... T, std::size_t... I>
|
||
|
std::array<field_view, sizeof...(T)> tuple_to_array_impl(const std::tuple<T...>& t, mp11::index_sequence<I...>) noexcept
|
||
|
{
|
||
|
boost::ignore_unused(t); // MSVC gets confused if sizeof...(T) == 0
|
||
|
return std::array<field_view, sizeof...(T)>{{to_field(std::get<I>(t))...}};
|
||
|
}
|
||
|
|
||
|
template <class... T>
|
||
|
std::array<field_view, sizeof...(T)> tuple_to_array(const std::tuple<T...>& t) noexcept
|
||
|
{
|
||
|
return tuple_to_array_impl(t, mp11::make_index_sequence<sizeof...(T)>());
|
||
|
}
|
||
|
|
||
|
struct query_request_getter
|
||
|
{
|
||
|
any_execution_request value;
|
||
|
any_execution_request get() const noexcept { return value; }
|
||
|
};
|
||
|
inline query_request_getter make_request_getter(string_view q, std::vector<field_view>&) noexcept
|
||
|
{
|
||
|
return query_request_getter{q};
|
||
|
}
|
||
|
|
||
|
struct stmt_it_request_getter
|
||
|
{
|
||
|
statement stmt;
|
||
|
span<const field_view> params; // Points into the connection state's shared fields
|
||
|
|
||
|
any_execution_request get() const noexcept { return any_execution_request(stmt, params); }
|
||
|
};
|
||
|
|
||
|
template <class FieldViewFwdIterator>
|
||
|
inline stmt_it_request_getter make_request_getter(
|
||
|
const bound_statement_iterator_range<FieldViewFwdIterator>& req,
|
||
|
std::vector<field_view>& shared_fields
|
||
|
)
|
||
|
{
|
||
|
auto& impl = access::get_impl(req);
|
||
|
shared_fields.assign(impl.first, impl.last);
|
||
|
return {impl.stmt, shared_fields};
|
||
|
}
|
||
|
|
||
|
template <std::size_t N>
|
||
|
struct stmt_tuple_request_getter
|
||
|
{
|
||
|
statement stmt;
|
||
|
std::array<field_view, N> params;
|
||
|
|
||
|
any_execution_request get() const noexcept { return any_execution_request(stmt, params); }
|
||
|
};
|
||
|
template <class WritableFieldTuple>
|
||
|
stmt_tuple_request_getter<std::tuple_size<WritableFieldTuple>::value>
|
||
|
make_request_getter(const bound_statement_tuple<WritableFieldTuple>& req, std::vector<field_view>&)
|
||
|
{
|
||
|
auto& impl = access::get_impl(req);
|
||
|
return {impl.stmt, tuple_to_array(impl.params)};
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// helpers to run algos
|
||
|
//
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
using has_void_result = std::is_same<typename AlgoParams::result_type, void>;
|
||
|
|
||
|
template <class AlgoParams, bool is_void>
|
||
|
struct completion_signature_impl;
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
struct completion_signature_impl<AlgoParams, true>
|
||
|
{
|
||
|
// Using typedef to workaround a msvc 14.1 bug
|
||
|
typedef void(type)(error_code);
|
||
|
};
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
struct completion_signature_impl<AlgoParams, false>
|
||
|
{
|
||
|
// Using typedef to workaround a msvc 14.1 bug
|
||
|
typedef void(type)(error_code, typename AlgoParams::result_type);
|
||
|
};
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
using completion_signature_t = typename completion_signature_impl<
|
||
|
AlgoParams,
|
||
|
has_void_result<AlgoParams>::value>::type;
|
||
|
|
||
|
// Intermediate handler
|
||
|
template <class AlgoParams, class Handler>
|
||
|
struct generic_algo_handler
|
||
|
{
|
||
|
static_assert(!has_void_result<AlgoParams>::value, "Internal error: result_type should be non-void");
|
||
|
|
||
|
using result_t = typename AlgoParams::result_type;
|
||
|
|
||
|
template <class DeducedHandler>
|
||
|
generic_algo_handler(DeducedHandler&& h, connection_state& st)
|
||
|
: final_handler(std::forward<DeducedHandler>(h)), st(&st)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void operator()(error_code ec)
|
||
|
{
|
||
|
std::move(final_handler)(ec, ec ? result_t{} : get_result<AlgoParams>(*st));
|
||
|
}
|
||
|
|
||
|
Handler final_handler; // needs to be accessed by associator
|
||
|
connection_state* st;
|
||
|
};
|
||
|
|
||
|
class connection_impl
|
||
|
{
|
||
|
std::unique_ptr<engine> engine_;
|
||
|
std::unique_ptr<connection_state, connection_state_deleter> st_;
|
||
|
|
||
|
// Generic algorithm
|
||
|
template <class AlgoParams>
|
||
|
typename AlgoParams::result_type run_impl(
|
||
|
AlgoParams params,
|
||
|
error_code& ec,
|
||
|
std::true_type /* has_void_result */
|
||
|
)
|
||
|
{
|
||
|
engine_->run(setup(*st_, params), ec);
|
||
|
}
|
||
|
|
||
|
template <class AlgoParams>
|
||
|
typename AlgoParams::result_type run_impl(
|
||
|
AlgoParams params,
|
||
|
error_code& ec,
|
||
|
std::false_type /* has_void_result */
|
||
|
)
|
||
|
{
|
||
|
engine_->run(setup(*st_, params), ec);
|
||
|
return get_result<AlgoParams>(*st_);
|
||
|
}
|
||
|
|
||
|
template <class AlgoParams, class Handler>
|
||
|
static void async_run_impl(
|
||
|
engine& eng,
|
||
|
connection_state& st,
|
||
|
AlgoParams params,
|
||
|
Handler&& handler,
|
||
|
std::true_type /* has_void_result */
|
||
|
)
|
||
|
{
|
||
|
eng.async_run(setup(st, params), std::forward<Handler>(handler));
|
||
|
}
|
||
|
|
||
|
template <class AlgoParams, class Handler>
|
||
|
static void async_run_impl(
|
||
|
engine& eng,
|
||
|
connection_state& st,
|
||
|
AlgoParams params,
|
||
|
Handler&& handler,
|
||
|
std::false_type /* has_void_result */
|
||
|
)
|
||
|
{
|
||
|
using intermediate_handler_t = generic_algo_handler<AlgoParams, typename std::decay<Handler>::type>;
|
||
|
eng.async_run(setup(st, params), intermediate_handler_t(std::forward<Handler>(handler), st));
|
||
|
}
|
||
|
|
||
|
template <class AlgoParams, class Handler>
|
||
|
static void async_run_impl(engine& eng, connection_state& st, AlgoParams params, Handler&& handler)
|
||
|
{
|
||
|
async_run_impl(eng, st, params, std::forward<Handler>(handler), has_void_result<AlgoParams>{});
|
||
|
}
|
||
|
|
||
|
struct run_algo_initiation
|
||
|
{
|
||
|
template <class Handler, class AlgoParams>
|
||
|
void operator()(Handler&& handler, engine* eng, connection_state* st, AlgoParams params)
|
||
|
{
|
||
|
async_run_impl(*eng, *st, params, std::forward<Handler>(handler));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Connect
|
||
|
static connect_algo_params make_params_connect(diagnostics& diag, const handshake_params& params)
|
||
|
{
|
||
|
return connect_algo_params{&diag, params, false};
|
||
|
}
|
||
|
|
||
|
static connect_algo_params make_params_connect_v2(diagnostics& diag, const connect_params& params)
|
||
|
{
|
||
|
return connect_algo_params{
|
||
|
&diag,
|
||
|
make_hparams(params),
|
||
|
params.server_address.type() == address_type::unix_path
|
||
|
};
|
||
|
}
|
||
|
|
||
|
template <class EndpointType>
|
||
|
struct initiate_connect
|
||
|
{
|
||
|
template <class Handler>
|
||
|
void operator()(
|
||
|
Handler&& handler,
|
||
|
engine* eng,
|
||
|
connection_state* st,
|
||
|
const EndpointType& endpoint,
|
||
|
handshake_params params,
|
||
|
diagnostics* diag
|
||
|
)
|
||
|
{
|
||
|
eng->set_endpoint(&endpoint);
|
||
|
async_run_impl(*eng, *st, make_params_connect(*diag, params), std::forward<Handler>(handler));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct initiate_connect_v2
|
||
|
{
|
||
|
template <class Handler>
|
||
|
void operator()(
|
||
|
Handler&& handler,
|
||
|
engine* eng,
|
||
|
connection_state* st,
|
||
|
const connect_params* params,
|
||
|
diagnostics* diag
|
||
|
)
|
||
|
{
|
||
|
eng->set_endpoint(¶ms->server_address);
|
||
|
async_run_impl(*eng, *st, make_params_connect_v2(*diag, *params), std::forward<Handler>(handler));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// execute
|
||
|
struct initiate_execute
|
||
|
{
|
||
|
template <class Handler, class ExecutionRequest>
|
||
|
void operator()(
|
||
|
Handler&& handler,
|
||
|
engine* eng,
|
||
|
connection_state* st,
|
||
|
const ExecutionRequest& req,
|
||
|
execution_processor* proc,
|
||
|
diagnostics* diag
|
||
|
)
|
||
|
{
|
||
|
auto getter = make_request_getter(req, get_shared_fields(*st));
|
||
|
async_run_impl(
|
||
|
*eng,
|
||
|
*st,
|
||
|
execute_algo_params{diag, getter.get(), proc},
|
||
|
std::forward<Handler>(handler)
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// start execution
|
||
|
struct initiate_start_execution
|
||
|
{
|
||
|
template <class Handler, class ExecutionRequest>
|
||
|
void operator()(
|
||
|
Handler&& handler,
|
||
|
engine* eng,
|
||
|
connection_state* st,
|
||
|
const ExecutionRequest& req,
|
||
|
execution_processor* proc,
|
||
|
diagnostics* diag
|
||
|
)
|
||
|
{
|
||
|
auto getter = make_request_getter(req, get_shared_fields(*st));
|
||
|
async_run_impl(
|
||
|
*eng,
|
||
|
*st,
|
||
|
start_execution_algo_params{diag, getter.get(), proc},
|
||
|
std::forward<Handler>(handler)
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
BOOST_MYSQL_DECL connection_impl(
|
||
|
std::size_t read_buff_size,
|
||
|
std::size_t max_buffer_size,
|
||
|
std::unique_ptr<engine> eng
|
||
|
);
|
||
|
|
||
|
BOOST_MYSQL_DECL metadata_mode meta_mode() const;
|
||
|
BOOST_MYSQL_DECL void set_meta_mode(metadata_mode m);
|
||
|
BOOST_MYSQL_DECL bool ssl_active() const;
|
||
|
BOOST_MYSQL_DECL bool backslash_escapes() const;
|
||
|
BOOST_MYSQL_DECL system::result<character_set> current_character_set() const;
|
||
|
BOOST_MYSQL_DECL diagnostics& shared_diag(); // TODO: get rid of this
|
||
|
|
||
|
engine& get_engine()
|
||
|
{
|
||
|
BOOST_ASSERT(engine_);
|
||
|
return *engine_;
|
||
|
}
|
||
|
|
||
|
const engine& get_engine() const
|
||
|
{
|
||
|
BOOST_ASSERT(engine_);
|
||
|
return *engine_;
|
||
|
}
|
||
|
|
||
|
// Generic algorithm
|
||
|
template <class AlgoParams>
|
||
|
typename AlgoParams::result_type run(AlgoParams params, error_code& ec)
|
||
|
{
|
||
|
return run_impl(params, ec, has_void_result<AlgoParams>{});
|
||
|
}
|
||
|
|
||
|
template <class AlgoParams, class CompletionToken>
|
||
|
auto async_run(AlgoParams params, CompletionToken&& token)
|
||
|
-> decltype(asio::async_initiate<CompletionToken, completion_signature_t<AlgoParams>>(
|
||
|
run_algo_initiation(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
params
|
||
|
))
|
||
|
{
|
||
|
return asio::async_initiate<CompletionToken, completion_signature_t<AlgoParams>>(
|
||
|
run_algo_initiation(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
params
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Connect
|
||
|
template <class EndpointType>
|
||
|
void connect(
|
||
|
const EndpointType& endpoint,
|
||
|
const handshake_params& params,
|
||
|
error_code& err,
|
||
|
diagnostics& diag
|
||
|
)
|
||
|
{
|
||
|
engine_->set_endpoint(&endpoint);
|
||
|
run(make_params_connect(diag, params), err);
|
||
|
}
|
||
|
|
||
|
void connect_v2(const connect_params& params, error_code& err, diagnostics& diag)
|
||
|
{
|
||
|
engine_->set_endpoint(¶ms.server_address);
|
||
|
run(make_params_connect_v2(diag, params), err);
|
||
|
}
|
||
|
|
||
|
template <class EndpointType, class CompletionToken>
|
||
|
auto async_connect(
|
||
|
const EndpointType& endpoint,
|
||
|
const handshake_params& params,
|
||
|
diagnostics& diag,
|
||
|
CompletionToken&& token
|
||
|
)
|
||
|
-> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_connect<EndpointType>(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
endpoint,
|
||
|
params,
|
||
|
&diag
|
||
|
))
|
||
|
{
|
||
|
return asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_connect<EndpointType>(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
endpoint,
|
||
|
params,
|
||
|
&diag
|
||
|
);
|
||
|
}
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
auto async_connect_v2(const connect_params& params, diagnostics& diag, CompletionToken&& token)
|
||
|
-> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_connect_v2(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
¶ms,
|
||
|
&diag
|
||
|
))
|
||
|
{
|
||
|
return asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_connect_v2(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
¶ms,
|
||
|
&diag
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Handshake
|
||
|
handshake_algo_params make_params_handshake(const handshake_params& params, diagnostics& diag) const
|
||
|
{
|
||
|
return {&diag, params, false};
|
||
|
}
|
||
|
|
||
|
// Execute
|
||
|
template <class ExecutionRequest, class ResultsType>
|
||
|
void execute(const ExecutionRequest& req, ResultsType& result, error_code& err, diagnostics& diag)
|
||
|
{
|
||
|
auto getter = make_request_getter(req, get_shared_fields(*st_));
|
||
|
run(execute_algo_params{&diag, getter.get(), &access::get_impl(result).get_interface()}, err);
|
||
|
}
|
||
|
|
||
|
template <class ExecutionRequest, class ResultsType, class CompletionToken>
|
||
|
auto async_execute(
|
||
|
ExecutionRequest&& req,
|
||
|
ResultsType& result,
|
||
|
diagnostics& diag,
|
||
|
CompletionToken&& token
|
||
|
)
|
||
|
-> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_execute(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
std::forward<ExecutionRequest>(req),
|
||
|
&access::get_impl(result).get_interface(),
|
||
|
&diag
|
||
|
))
|
||
|
{
|
||
|
return asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_execute(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
std::forward<ExecutionRequest>(req),
|
||
|
&access::get_impl(result).get_interface(),
|
||
|
&diag
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Start execution
|
||
|
template <class ExecutionRequest, class ExecutionStateType>
|
||
|
void start_execution(
|
||
|
const ExecutionRequest& req,
|
||
|
ExecutionStateType& exec_st,
|
||
|
error_code& err,
|
||
|
diagnostics& diag
|
||
|
)
|
||
|
{
|
||
|
auto getter = make_request_getter(req, get_shared_fields(*st_));
|
||
|
run(start_execution_algo_params{&diag, getter.get(), &access::get_impl(exec_st).get_interface()},
|
||
|
err);
|
||
|
}
|
||
|
|
||
|
template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
|
||
|
auto async_start_execution(
|
||
|
ExecutionRequest&& req,
|
||
|
ExecutionStateType& exec_st,
|
||
|
diagnostics& diag,
|
||
|
CompletionToken&& token
|
||
|
)
|
||
|
-> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_start_execution(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
std::forward<ExecutionRequest>(req),
|
||
|
&access::get_impl(exec_st).get_interface(),
|
||
|
&diag
|
||
|
))
|
||
|
{
|
||
|
return asio::async_initiate<CompletionToken, void(error_code)>(
|
||
|
initiate_start_execution(),
|
||
|
token,
|
||
|
engine_.get(),
|
||
|
st_.get(),
|
||
|
std::forward<ExecutionRequest>(req),
|
||
|
&access::get_impl(exec_st).get_interface(),
|
||
|
&diag
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Read some rows (dynamic)
|
||
|
read_some_rows_dynamic_algo_params make_params_read_some_rows(execution_state& st, diagnostics& diag)
|
||
|
const
|
||
|
{
|
||
|
return {&diag, &access::get_impl(st).get_interface()};
|
||
|
}
|
||
|
|
||
|
// Read some rows (static)
|
||
|
template <class SpanElementType, class ExecutionState>
|
||
|
read_some_rows_algo_params make_params_read_some_rows_static(
|
||
|
ExecutionState& exec_st,
|
||
|
span<SpanElementType> output,
|
||
|
diagnostics& diag
|
||
|
) const
|
||
|
{
|
||
|
return {
|
||
|
&diag,
|
||
|
&access::get_impl(exec_st).get_interface(),
|
||
|
access::get_impl(exec_st).make_output_ref(output)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Read resultset head
|
||
|
template <class ExecutionStateType>
|
||
|
read_resultset_head_algo_params make_params_read_resultset_head(ExecutionStateType& st, diagnostics& diag)
|
||
|
const
|
||
|
{
|
||
|
return {&diag, &detail::access::get_impl(st).get_interface()};
|
||
|
}
|
||
|
|
||
|
// Close statement
|
||
|
close_statement_algo_params make_params_close_statement(statement stmt, diagnostics& diag) const
|
||
|
{
|
||
|
return {&diag, stmt.id()};
|
||
|
}
|
||
|
|
||
|
// Set character set
|
||
|
set_character_set_algo_params make_params_set_character_set(
|
||
|
const character_set& charset,
|
||
|
diagnostics& diag
|
||
|
) const
|
||
|
{
|
||
|
return {&diag, charset};
|
||
|
}
|
||
|
|
||
|
// Ping
|
||
|
ping_algo_params make_params_ping(diagnostics& diag) const { return {&diag}; }
|
||
|
|
||
|
// Reset connection
|
||
|
reset_connection_algo_params make_params_reset_connection(diagnostics& diag) const { return {&diag}; }
|
||
|
|
||
|
// Quit connection
|
||
|
quit_connection_algo_params make_params_quit(diagnostics& diag) const { return {&diag}; }
|
||
|
|
||
|
// Close connection
|
||
|
close_connection_algo_params make_params_close(diagnostics& diag) const { return {&diag}; }
|
||
|
|
||
|
// Run pipeline. Separately compiled to avoid including the pipeline header here
|
||
|
BOOST_MYSQL_DECL
|
||
|
static run_pipeline_algo_params make_params_pipeline(
|
||
|
const pipeline_request& req,
|
||
|
std::vector<stage_response>& response,
|
||
|
diagnostics& diag
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// To use some completion tokens, like deferred, in C++11, the old macros
|
||
|
// BOOST_ASIO_INITFN_AUTO_RESULT_TYPE are no longer enough.
|
||
|
// Helper typedefs to reduce duplication
|
||
|
template <class AlgoParams, class CompletionToken>
|
||
|
using async_run_t = decltype(std::declval<connection_impl&>()
|
||
|
.async_run(std::declval<AlgoParams>(), std::declval<CompletionToken>()));
|
||
|
|
||
|
template <class EndpointType, class CompletionToken>
|
||
|
using async_connect_t = decltype(std::declval<connection_impl&>().async_connect(
|
||
|
std::declval<const EndpointType&>(),
|
||
|
std::declval<const handshake_params&>(),
|
||
|
std::declval<diagnostics&>(),
|
||
|
std::declval<CompletionToken>()
|
||
|
));
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_connect_v2_t = decltype(std::declval<connection_impl&>().async_connect_v2(
|
||
|
std::declval<const connect_params&>(),
|
||
|
std::declval<diagnostics&>(),
|
||
|
std::declval<CompletionToken>()
|
||
|
));
|
||
|
|
||
|
template <class ExecutionRequest, class ResultsType, class CompletionToken>
|
||
|
using async_execute_t = decltype(std::declval<connection_impl&>().async_execute(
|
||
|
std::declval<ExecutionRequest>(),
|
||
|
std::declval<ResultsType&>(),
|
||
|
std::declval<diagnostics&>(),
|
||
|
std::declval<CompletionToken>()
|
||
|
));
|
||
|
|
||
|
template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
|
||
|
using async_start_execution_t = decltype(std::declval<connection_impl&>().async_start_execution(
|
||
|
std::declval<ExecutionRequest>(),
|
||
|
std::declval<ExecutionStateType&>(),
|
||
|
std::declval<diagnostics&>(),
|
||
|
std::declval<CompletionToken>()
|
||
|
));
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_handshake_t = async_run_t<handshake_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_read_resultset_head_t = async_run_t<read_resultset_head_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_read_some_rows_dynamic_t = async_run_t<read_some_rows_dynamic_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_prepare_statement_t = async_run_t<prepare_statement_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_close_statement_t = async_run_t<close_statement_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_set_character_set_t = async_run_t<set_character_set_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_ping_t = async_run_t<ping_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_reset_connection_t = async_run_t<reset_connection_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_quit_connection_t = async_run_t<quit_connection_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_close_connection_t = async_run_t<close_connection_algo_params, CompletionToken>;
|
||
|
|
||
|
template <class CompletionToken>
|
||
|
using async_run_pipeline_t = async_run_t<run_pipeline_algo_params, CompletionToken>;
|
||
|
|
||
|
} // namespace detail
|
||
|
} // namespace mysql
|
||
|
} // namespace boost
|
||
|
|
||
|
// Propagate associated properties
|
||
|
namespace boost {
|
||
|
namespace asio {
|
||
|
|
||
|
template <template <class, class> class Associator, class AlgoParams, class Handler, class DefaultCandidate>
|
||
|
struct associator<Associator, mysql::detail::generic_algo_handler<AlgoParams, Handler>, DefaultCandidate>
|
||
|
: Associator<Handler, DefaultCandidate>
|
||
|
{
|
||
|
using mysql_handler = mysql::detail::generic_algo_handler<AlgoParams, Handler>;
|
||
|
|
||
|
static typename Associator<Handler, DefaultCandidate>::type get(const mysql_handler& h)
|
||
|
{
|
||
|
return Associator<Handler, DefaultCandidate>::get(h.final_handler);
|
||
|
}
|
||
|
|
||
|
static auto get(const mysql_handler& h, const DefaultCandidate& c)
|
||
|
-> decltype(Associator<Handler, DefaultCandidate>::get(h.final_handler, c))
|
||
|
{
|
||
|
return Associator<Handler, DefaultCandidate>::get(h.final_handler, c);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace asio
|
||
|
} // namespace boost
|
||
|
|
||
|
#ifdef BOOST_MYSQL_HEADER_ONLY
|
||
|
#include <boost/mysql/impl/connection_impl.ipp>
|
||
|
#endif
|
||
|
|
||
|
#endif
|