123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- //
- // Copyright (c) 2019-2023 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 BHO_MYSQL_DETAIL_NETWORK_ALGORITHMS_HPP
- #define BHO_MYSQL_DETAIL_NETWORK_ALGORITHMS_HPP
- #include <asio2/bho/mysql/diagnostics.hpp>
- #include <asio2/bho/mysql/error_code.hpp>
- #include <asio2/bho/mysql/execution_state.hpp>
- #include <asio2/bho/mysql/field_view.hpp>
- #include <asio2/bho/mysql/handshake_params.hpp>
- #include <asio2/bho/mysql/rows_view.hpp>
- #include <asio2/bho/mysql/statement.hpp>
- #include <asio2/bho/mysql/string_view.hpp>
- #include <asio2/bho/mysql/detail/access.hpp>
- #include <asio2/bho/mysql/detail/any_execution_request.hpp>
- #include <asio2/bho/mysql/detail/channel_ptr.hpp>
- #include <asio2/bho/mysql/detail/config.hpp>
- #include <asio2/bho/mysql/detail/execution_processor/execution_processor.hpp>
- #include <asio2/bho/mysql/detail/typing/get_type_index.hpp>
- #include <asio/any_completion_handler.hpp>
- #include <asio2/bho/mp11/integer_sequence.hpp>
- #include <array>
- #include <cstddef>
- namespace bho {
- namespace mysql {
- template <class... StaticRow>
- class static_execution_state;
- namespace detail {
- class channel;
- template <class T>
- using any_handler = asio::any_completion_handler<void(error_code, T)>;
- using any_void_handler = asio::any_completion_handler<void(error_code)>;
- // 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
- {
- 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, channel&) noexcept
- {
- return query_request_getter{q};
- }
- struct stmt_it_request_getter
- {
- statement stmt;
- span<const field_view> params; // Points into channel 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,
- channel& chan
- )
- {
- auto& impl = access::get_impl(req);
- auto& shared_fields = get_shared_fields(chan);
- 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, channel&)
- {
- auto& impl = access::get_impl(req);
- return {impl.stmt, tuple_to_array(impl.params)};
- }
- //
- // connect
- //
- BHO_MYSQL_DECL
- void connect_erased(
- channel& chan,
- const void* endpoint,
- const handshake_params& params,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL
- void async_connect_erased(
- channel& chan,
- const void* endpoint,
- const handshake_params& params,
- diagnostics& diag,
- any_void_handler handler
- );
- // Handles casting from the generic EndpointType we've got in the interface to the concrete endpoint type
- template <class Stream>
- void connect_interface(
- channel& chan,
- const typename Stream::lowest_layer_type::endpoint_type& ep,
- const handshake_params& params,
- error_code& err,
- diagnostics& diag
- )
- {
- connect_erased(chan, &ep, params, err, diag);
- }
- template <class Stream>
- struct connect_initiation
- {
- template <class Handler>
- void operator()(
- Handler&& handler,
- channel* chan,
- const typename Stream::lowest_layer_type::endpoint_type& endpoint,
- handshake_params params,
- diagnostics* diag
- )
- {
- async_connect_erased(*chan, &endpoint, params, *diag, std::forward<Handler>(handler));
- }
- };
- template <class Stream, class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_connect_interface(
- channel& chan,
- const typename Stream::lowest_layer_type::endpoint_type& endpoint,
- const handshake_params& params,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- connect_initiation<Stream>(),
- token,
- &chan,
- endpoint,
- params,
- &diag
- );
- }
- //
- // handshake
- //
- BHO_MYSQL_DECL
- void handshake_erased(channel& channel, const handshake_params& params, error_code& err, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_handshake_erased(
- channel& chan,
- const handshake_params& params,
- diagnostics& diag,
- any_void_handler
- );
- inline void handshake_interface(
- channel& channel,
- const handshake_params& params,
- error_code& err,
- diagnostics& diag
- )
- {
- handshake_erased(channel, params, err, diag);
- }
- struct handshake_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, handshake_params params, diagnostics* diag)
- {
- async_handshake_erased(*chan, params, *diag, std::forward<Handler>(handler));
- }
- };
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_handshake_interface(
- channel& chan,
- const handshake_params& params,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- handshake_initiation(),
- token,
- &chan,
- params,
- &diag
- );
- }
- //
- // execute
- //
- BHO_MYSQL_DECL
- void execute_erased(
- channel& channel,
- const any_execution_request& req,
- execution_processor& output,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL void async_execute_erased(
- channel& chan,
- const any_execution_request& req,
- execution_processor& output,
- diagnostics& diag,
- any_void_handler handler
- );
- struct initiate_execute
- {
- template <class Handler, class ExecutionRequest>
- void operator()(
- Handler&& handler,
- channel& chan,
- const ExecutionRequest& req,
- execution_processor& proc,
- diagnostics& diag
- )
- {
- auto getter = make_request_getter(req, chan);
- async_execute_erased(chan, getter.get(), proc, diag, std::forward<Handler>(handler));
- }
- };
- template <class ExecutionRequest, class ResultsType>
- void execute_interface(
- channel& channel,
- const ExecutionRequest& req,
- ResultsType& result,
- error_code& err,
- diagnostics& diag
- )
- {
- auto getter = make_request_getter(req, channel);
- execute_erased(channel, getter.get(), access::get_impl(result).get_interface(), err, diag);
- }
- template <class ExecutionRequest, class ResultsType, class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_execute_interface(
- channel& chan,
- ExecutionRequest&& req,
- ResultsType& result,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- initiate_execute(),
- token,
- std::ref(chan),
- std::forward<ExecutionRequest>(req),
- std::ref(access::get_impl(result).get_interface()),
- std::ref(diag)
- );
- }
- //
- // start_execution
- //
- BHO_MYSQL_DECL
- void start_execution_erased(
- channel& channel,
- const any_execution_request& req,
- execution_processor& proc,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL
- void async_start_execution_erased(
- channel& channel,
- const any_execution_request& req,
- execution_processor& proc,
- diagnostics& diag,
- any_void_handler handler
- );
- struct initiate_start_execution
- {
- template <class Handler, class ExecutionRequest>
- void operator()(
- Handler&& handler,
- channel& chan,
- const ExecutionRequest& req,
- execution_processor& proc,
- diagnostics& diag
- )
- {
- auto getter = make_request_getter(req, chan);
- async_start_execution_erased(chan, getter.get(), proc, diag, std::forward<Handler>(handler));
- }
- };
- template <class ExecutionRequest, class ExecutionStateType>
- void start_execution_interface(
- channel& channel,
- const ExecutionRequest& req,
- ExecutionStateType& st,
- error_code& err,
- diagnostics& diag
- )
- {
- auto getter = make_request_getter(req, channel);
- start_execution_erased(channel, getter.get(), access::get_impl(st).get_interface(), err, diag);
- }
- template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_start_execution_interface(
- channel& chan,
- ExecutionRequest&& req,
- ExecutionStateType& st,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- initiate_start_execution(),
- token,
- std::ref(chan),
- std::forward<ExecutionRequest>(req),
- std::ref(access::get_impl(st).get_interface()),
- std::ref(diag)
- );
- }
- //
- // prepare_statement
- //
- BHO_MYSQL_DECL
- statement prepare_statement_erased(channel& chan, string_view stmt, error_code& err, diagnostics& diag);
- BHO_MYSQL_DECL void async_prepare_statement_erased(
- channel& chan,
- string_view stmt,
- diagnostics& diag,
- any_handler<statement> handler
- );
- struct prepare_statement_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, string_view stmt_sql, diagnostics* diag)
- {
- async_prepare_statement_erased(*chan, stmt_sql, *diag, std::forward<Handler>(handler));
- }
- };
- inline statement prepare_statement_interface(
- channel& chan,
- string_view stmt,
- error_code& err,
- diagnostics& diag
- )
- {
- return prepare_statement_erased(chan, stmt, err, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(bho::mysql::error_code, bho::mysql::statement))
- async_prepare_statement_interface(channel& chan, string_view stmt, diagnostics& diag, CompletionToken&& token)
- {
- return asio::async_initiate<CompletionToken, void(error_code, statement)>(
- prepare_statement_initiation(),
- token,
- &chan,
- stmt,
- &diag
- );
- }
- //
- // close_statement
- //
- BHO_MYSQL_DECL
- void close_statement_erased(channel& chan, const statement& stmt, error_code& err, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_close_statement_erased(
- channel& chan,
- const statement& stmt,
- diagnostics& diag,
- any_void_handler handler
- );
- struct close_statement_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, statement stmt, diagnostics* diag)
- {
- async_close_statement_erased(*chan, stmt, *diag, std::forward<Handler>(handler));
- }
- };
- inline void close_statement_interface(
- channel& chan,
- const statement& stmt,
- error_code& err,
- diagnostics& diag
- )
- {
- close_statement_erased(chan, stmt, err, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_close_statement_interface(
- channel& chan,
- const statement& stmt,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- close_statement_initiation(),
- token,
- &chan,
- stmt,
- &diag
- );
- }
- //
- // read_some_rows (dynamic)
- //
- BHO_MYSQL_DECL
- rows_view read_some_rows_dynamic_erased(
- channel& chan,
- execution_state_impl& st,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL void async_read_some_rows_dynamic_erased(
- channel& chan,
- execution_state_impl& st,
- diagnostics& diag,
- any_handler<rows_view> handler
- );
- struct read_some_rows_dynamic_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, execution_state_impl* st, diagnostics* diag)
- {
- async_read_some_rows_dynamic_erased(*chan, *st, *diag, std::forward<Handler>(handler));
- }
- };
- inline rows_view read_some_rows_dynamic_interface(
- channel& chan,
- execution_state& st,
- error_code& err,
- diagnostics& diag
- )
- {
- return read_some_rows_dynamic_erased(chan, access::get_impl(st), err, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
- async_read_some_rows_dynamic_interface(
- channel& chan,
- execution_state& st,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code, rows_view)>(
- read_some_rows_dynamic_initiation(),
- token,
- &chan,
- &access::get_impl(st).get_interface(),
- &diag
- );
- }
- //
- // read_some_rows (static)
- //
- BHO_MYSQL_DECL
- std::size_t read_some_rows_static_erased(
- channel& chan,
- execution_processor& proc,
- const output_ref& output,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL
- void async_read_some_rows_erased(
- channel& chan,
- execution_processor& proc,
- const output_ref& output,
- diagnostics& diag,
- any_handler<std::size_t> handler
- );
- template <class SpanRowType, class... RowType>
- std::size_t read_some_rows_static_interface(
- channel& chan,
- static_execution_state<RowType...>& st,
- span<SpanRowType> output,
- error_code& err,
- diagnostics& diag
- )
- {
- constexpr std::size_t index = get_type_index<SpanRowType, RowType...>();
- static_assert(index != index_not_found, "SpanRowType must be one of the types returned by the query");
- return read_some_rows_static_erased(
- chan,
- access::get_impl(st).get_interface(),
- output_ref(output, index),
- err,
- diag
- );
- }
- struct read_some_rows_static_initiation
- {
- template <class Handler>
- void operator()(
- Handler&& handler,
- channel* chan,
- execution_processor* proc,
- const output_ref& output,
- diagnostics* diag
- )
- {
- async_read_some_rows_erased(*chan, *proc, output, *diag, std::forward<Handler>(handler));
- }
- };
- template <
- class SpanRowType,
- class... RowType,
- ASIO_COMPLETION_TOKEN_FOR(void(::bho::mysql::error_code, std::size_t)) CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
- async_read_some_rows_static_interface(
- channel& chan,
- static_execution_state<RowType...>& st,
- span<SpanRowType> output,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- constexpr std::size_t index = get_type_index<SpanRowType, RowType...>();
- static_assert(index != index_not_found, "SpanRowType must be one of the types returned by the query");
- return asio::async_initiate<CompletionToken, void(error_code, std::size_t)>(
- read_some_rows_static_initiation(),
- token,
- &chan,
- &access::get_impl(st).get_interface(),
- output_ref(output, index),
- &diag
- );
- }
- //
- // read_resultset_head
- //
- BHO_MYSQL_DECL
- void read_resultset_head_erased(
- channel& channel,
- execution_processor& proc,
- error_code& err,
- diagnostics& diag
- );
- BHO_MYSQL_DECL
- void async_read_resultset_head_erased(
- channel& chan,
- execution_processor& proc,
- diagnostics& diag,
- any_void_handler handler
- );
- template <class ExecutionStateType>
- void read_resultset_head_interface(
- channel& channel,
- ExecutionStateType& st,
- error_code& err,
- diagnostics& diag
- )
- {
- read_resultset_head_erased(channel, access::get_impl(st).get_interface(), err, diag);
- }
- struct read_resultset_head_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, execution_processor* proc, diagnostics* diag)
- {
- async_read_resultset_head_erased(*chan, *proc, *diag, std::forward<Handler>(handler));
- }
- };
- template <class CompletionToken, class ExecutionStateType>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_read_resultset_head_interface(
- channel& chan,
- ExecutionStateType& st,
- diagnostics& diag,
- CompletionToken&& token
- )
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- read_resultset_head_initiation(),
- token,
- &chan,
- &access::get_impl(st).get_interface(),
- &diag
- );
- }
- //
- // ping
- //
- BHO_MYSQL_DECL
- void ping_erased(channel& chan, error_code& code, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_ping_erased(channel& chan, diagnostics& diag, any_void_handler handler);
- struct ping_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, diagnostics* diag)
- {
- async_ping_erased(*chan, *diag, std::forward<Handler>(handler));
- }
- };
- inline void ping_interface(channel& chan, error_code& code, diagnostics& diag)
- {
- ping_erased(chan, code, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_ping_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(ping_initiation(), token, &chan, &diag);
- }
- //
- // reset_connection
- //
- BHO_MYSQL_DECL
- void reset_connection_erased(channel& chan, error_code& code, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_reset_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
- struct reset_connection_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, diagnostics* diag)
- {
- async_reset_connection_erased(*chan, *diag, std::forward<Handler>(handler));
- }
- };
- inline void reset_connection_interface(channel& chan, error_code& code, diagnostics& diag)
- {
- reset_connection_erased(chan, code, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_reset_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- reset_connection_initiation(),
- token,
- &chan,
- &diag
- );
- }
- //
- // close connection
- //
- BHO_MYSQL_DECL
- void close_connection_erased(channel& chan, error_code& code, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_close_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
- struct close_connection_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, diagnostics* diag)
- {
- async_close_connection_erased(*chan, *diag, std::forward<Handler>(handler));
- }
- };
- inline void close_connection_interface(channel& chan, error_code& code, diagnostics& diag)
- {
- close_connection_erased(chan, code, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_close_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- close_connection_initiation(),
- token,
- &chan,
- &diag
- );
- }
- //
- // quit connection
- //
- BHO_MYSQL_DECL
- void quit_connection_erased(channel& chan, error_code& err, diagnostics& diag);
- BHO_MYSQL_DECL
- void async_quit_connection_erased(channel& chan, diagnostics& diag, any_void_handler handler);
- struct quit_connection_initiation
- {
- template <class Handler>
- void operator()(Handler&& handler, channel* chan, diagnostics* diag)
- {
- async_quit_connection_erased(*chan, *diag, std::forward<Handler>(handler));
- }
- };
- inline void quit_connection_interface(channel& chan, error_code& err, diagnostics& diag)
- {
- quit_connection_erased(chan, err, diag);
- }
- template <class CompletionToken>
- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
- async_quit_connection_interface(channel& chan, diagnostics& diag, CompletionToken&& token)
- {
- return asio::async_initiate<CompletionToken, void(error_code)>(
- quit_connection_initiation(),
- token,
- &chan,
- &diag
- );
- }
- } // namespace detail
- } // namespace mysql
- } // namespace bho
- #ifdef BHO_MYSQL_HEADER_ONLY
- #include <asio2/bho/mysql/impl/network_algorithms.ipp>
- #endif
- #endif
|