connection.hpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. //
  2. // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_CONNECTION_HPP
  8. #define BOOST_MYSQL_CONNECTION_HPP
  9. #include <boost/mysql/buffer_params.hpp>
  10. #include <boost/mysql/defaults.hpp>
  11. #include <boost/mysql/diagnostics.hpp>
  12. #include <boost/mysql/error_code.hpp>
  13. #include <boost/mysql/execution_state.hpp>
  14. #include <boost/mysql/handshake_params.hpp>
  15. #include <boost/mysql/metadata_mode.hpp>
  16. #include <boost/mysql/results.hpp>
  17. #include <boost/mysql/rows_view.hpp>
  18. #include <boost/mysql/statement.hpp>
  19. #include <boost/mysql/string_view.hpp>
  20. #include <boost/mysql/detail/access.hpp>
  21. #include <boost/mysql/detail/algo_params.hpp>
  22. #include <boost/mysql/detail/connection_impl.hpp>
  23. #include <boost/mysql/detail/engine_stream_adaptor.hpp>
  24. #include <boost/mysql/detail/execution_concepts.hpp>
  25. #include <boost/mysql/detail/rebind_executor.hpp>
  26. #include <boost/mysql/detail/socket_stream.hpp>
  27. #include <boost/mysql/detail/throw_on_error_loc.hpp>
  28. #include <boost/mysql/detail/writable_field_traits.hpp>
  29. #include <boost/assert.hpp>
  30. #include <cstddef>
  31. #include <type_traits>
  32. #include <utility>
  33. /// The Boost libraries namespace.
  34. namespace boost {
  35. /// Boost.MySQL library namespace.
  36. namespace mysql {
  37. // Forward declarations
  38. template <class... StaticRow>
  39. class static_execution_state;
  40. /**
  41. * \brief (Legacy) A connection to a MySQL server.
  42. * \details
  43. * Represents a templated connection to a MySQL server.
  44. *
  45. * `connection` owns a `Stream` object that
  46. * is accessed by functions involving network operations, as well as session state. You can access
  47. * the stream using \ref connection::stream, and its executor via \ref connection::get_executor. The
  48. * executor used by this object is always the same as the underlying stream.
  49. *
  50. * \par Single outstanding async operation per connection
  51. * At any given point in time, only one async operation can be outstanding
  52. * per connection. If an async operation is initiated while another one is in progress,
  53. * it will fail with \ref client_errc::operation_in_progress.
  54. *
  55. * \par Thread safety
  56. * Distinct objects: safe. \n
  57. * Shared objects: unsafe. \n
  58. * This class is <b>not thread-safe</b>: for a single object, if you
  59. * call its member functions concurrently from separate threads, you will get a race condition.
  60. *
  61. * \par Legacy
  62. * New code should use \ref any_connection instead of this class, as it's simpler to use
  63. * and provides the same level of performance.
  64. */
  65. template <class Stream>
  66. class connection
  67. {
  68. detail::connection_impl impl_;
  69. public:
  70. /**
  71. * \brief Initializing constructor.
  72. * \details
  73. * As part of the initialization, an internal `Stream` object is created.
  74. *
  75. * \par Exception safety
  76. * Basic guarantee. Throws if the `Stream` constructor throws
  77. * or if memory allocation for internal state fails.
  78. *
  79. * \param args Arguments to be forwarded to the `Stream` constructor.
  80. */
  81. template <
  82. class... Args,
  83. class EnableIf = typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type>
  84. connection(Args&&... args) : connection(buffer_params(), std::forward<Args>(args)...)
  85. {
  86. }
  87. /**
  88. * \brief Initializing constructor with buffer params.
  89. * \details
  90. * As part of the initialization, an internal `Stream` object is created.
  91. *
  92. * \par Exception safety
  93. * Basic guarantee. Throws if the `Stream` constructor throws
  94. * or if memory allocation for internal state fails.
  95. *
  96. * \param buff_params Specifies initial sizes for internal buffers.
  97. * \param args Arguments to be forwarded to the `Stream` constructor.
  98. */
  99. template <
  100. class... Args,
  101. class EnableIf = typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type>
  102. connection(const buffer_params& buff_params, Args&&... args)
  103. : impl_(
  104. buff_params.initial_read_size(),
  105. static_cast<std::size_t>(-1),
  106. detail::make_engine<Stream>(std::forward<Args>(args)...)
  107. )
  108. {
  109. }
  110. /**
  111. * \brief Move constructor.
  112. */
  113. connection(connection&& other) = default;
  114. /**
  115. * \brief Move assignment.
  116. */
  117. connection& operator=(connection&& rhs) = default;
  118. #ifndef BOOST_MYSQL_DOXYGEN
  119. connection(const connection&) = delete;
  120. connection& operator=(const connection&) = delete;
  121. #endif
  122. /// The executor type associated to this object.
  123. using executor_type = typename Stream::executor_type;
  124. /// Retrieves the executor associated to this object.
  125. executor_type get_executor() { return stream().get_executor(); }
  126. /// The `Stream` type this connection is using.
  127. using stream_type = Stream;
  128. /**
  129. * \brief Retrieves the underlying Stream object.
  130. * \details
  131. *
  132. * \par Exception safety
  133. * No-throw guarantee.
  134. */
  135. Stream& stream() noexcept { return detail::stream_from_engine<Stream>(impl_.get_engine()); }
  136. /**
  137. * \brief Retrieves the underlying Stream object.
  138. * \details
  139. *
  140. * \par Exception safety
  141. * No-throw guarantee.
  142. */
  143. const Stream& stream() const noexcept { return detail::stream_from_engine<Stream>(impl_.get_engine()); }
  144. /**
  145. * \brief Returns whether the connection negotiated the use of SSL or not.
  146. * \details
  147. * This function can be used to determine whether you are using a SSL
  148. * connection or not when using SSL negotiation.
  149. * \n
  150. * This function always returns `false` if the underlying
  151. * stream does not support SSL. This function always returns `false`
  152. * for connections that haven't been
  153. * established yet (handshake not run yet). If the handshake fails,
  154. * the return value is undefined.
  155. *
  156. * \par Exception safety
  157. * No-throw guarantee.
  158. *
  159. * \returns Whether the connection is using SSL.
  160. */
  161. bool uses_ssl() const noexcept { return impl_.ssl_active(); }
  162. /// \copydoc any_connection::meta_mode
  163. metadata_mode meta_mode() const noexcept { return impl_.meta_mode(); }
  164. /// \copydoc any_connection::set_meta_mode
  165. void set_meta_mode(metadata_mode v) noexcept { impl_.set_meta_mode(v); }
  166. /**
  167. * \brief Establishes a connection to a MySQL server.
  168. * \details
  169. * This function is only available if `Stream` satisfies the
  170. * `SocketStream` concept.
  171. * \n
  172. * Connects the underlying stream and performs the handshake
  173. * with the server. The underlying stream is closed in case of error. Prefer
  174. * this function to \ref connection::handshake.
  175. * \n
  176. * If using a SSL-capable stream, the SSL handshake will be performed by this function.
  177. * \n
  178. * `endpoint` should be convertible to `Stream::lowest_layer_type::endpoint_type`.
  179. */
  180. template <typename EndpointType>
  181. void connect(
  182. const EndpointType& endpoint,
  183. const handshake_params& params,
  184. error_code& ec,
  185. diagnostics& diag
  186. )
  187. {
  188. static_assert(
  189. detail::is_socket_stream<Stream>::value,
  190. "connect can only be used if Stream satisfies the SocketStream concept"
  191. );
  192. impl_.connect<typename Stream::lowest_layer_type::endpoint_type>(endpoint, params, ec, diag);
  193. }
  194. /// \copydoc connect
  195. template <typename EndpointType>
  196. void connect(const EndpointType& endpoint, const handshake_params& params)
  197. {
  198. static_assert(
  199. detail::is_socket_stream<Stream>::value,
  200. "connect can only be used if Stream satisfies the SocketStream concept"
  201. );
  202. error_code err;
  203. diagnostics diag;
  204. connect(endpoint, params, err, diag);
  205. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  206. }
  207. /**
  208. * \copydoc connect
  209. * \par Object lifetimes
  210. * The strings pointed to by `params` should be kept alive by the caller
  211. * until the operation completes, as no copy is made by the library.
  212. * `endpoint` is copied as required and doesn't need to be kept alive.
  213. *
  214. * \par Handler signature
  215. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  216. *
  217. * \par Executor
  218. * Intermediate completion handlers, as well as the final handler, are executed using
  219. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  220. * executor.
  221. *
  222. * If the final handler has an associated immediate executor, and the operation
  223. * completes immediately, the final handler is dispatched to it.
  224. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  225. * and is never be called inline from within this function.
  226. */
  227. template <
  228. typename EndpointType,
  229. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  230. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  231. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  232. async_connect(
  233. const EndpointType& endpoint,
  234. const handshake_params& params,
  235. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  236. )
  237. {
  238. static_assert(
  239. detail::is_socket_stream<Stream>::value,
  240. "async_connect can only be used if Stream satisfies the SocketStream concept"
  241. );
  242. return async_connect(endpoint, params, impl_.shared_diag(), std::forward<CompletionToken>(token));
  243. }
  244. /// \copydoc async_connect
  245. template <
  246. typename EndpointType,
  247. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  248. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  249. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  250. async_connect(
  251. const EndpointType& endpoint,
  252. const handshake_params& params,
  253. diagnostics& diag,
  254. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  255. )
  256. {
  257. static_assert(
  258. detail::is_socket_stream<Stream>::value,
  259. "async_connect can only be used if Stream satisfies the SocketStream concept"
  260. );
  261. return impl_.async_connect<typename Stream::lowest_layer_type::endpoint_type>(
  262. endpoint,
  263. params,
  264. diag,
  265. std::forward<CompletionToken>(token)
  266. );
  267. }
  268. /**
  269. * \brief Performs the MySQL-level handshake.
  270. * \details
  271. * Does not connect the underlying stream.
  272. * If the `Stream` template parameter fulfills the `SocketConnection`
  273. * requirements, use \ref connection::connect instead of this function.
  274. * \n
  275. * If using a SSL-capable stream, the SSL handshake will be performed by this function.
  276. */
  277. void handshake(const handshake_params& params, error_code& ec, diagnostics& diag)
  278. {
  279. impl_.run(impl_.make_params_handshake(params), ec, diag);
  280. }
  281. /// \copydoc handshake
  282. void handshake(const handshake_params& params)
  283. {
  284. error_code err;
  285. diagnostics diag;
  286. handshake(params, err, diag);
  287. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  288. }
  289. /**
  290. * \copydoc handshake
  291. * \par Object lifetimes
  292. * The strings pointed to by `params` should be kept alive by the caller
  293. * until the operation completes, as no copy is made by the library.
  294. *
  295. * \par Handler signature
  296. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  297. *
  298. * \par Executor
  299. * Intermediate completion handlers, as well as the final handler, are executed using
  300. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  301. * executor.
  302. *
  303. * If the final handler has an associated immediate executor, and the operation
  304. * completes immediately, the final handler is dispatched to it.
  305. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  306. * and is never be called inline from within this function.
  307. */
  308. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  309. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  310. auto async_handshake(
  311. const handshake_params& params,
  312. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  313. ) BOOST_MYSQL_RETURN_TYPE(detail::async_handshake_t<CompletionToken&&>)
  314. {
  315. return async_handshake(params, impl_.shared_diag(), std::forward<CompletionToken>(token));
  316. }
  317. /// \copydoc async_handshake
  318. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  319. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  320. auto async_handshake(
  321. const handshake_params& params,
  322. diagnostics& diag,
  323. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  324. ) BOOST_MYSQL_RETURN_TYPE(detail::async_handshake_t<CompletionToken&&>)
  325. {
  326. return impl_
  327. .async_run(impl_.make_params_handshake(params), diag, std::forward<CompletionToken>(token));
  328. }
  329. /// \copydoc any_connection::execute
  330. template <BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType>
  331. void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag)
  332. {
  333. impl_.execute(std::forward<ExecutionRequest>(req), result, err, diag);
  334. }
  335. /// \copydoc execute
  336. template <BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType>
  337. void execute(ExecutionRequest&& req, ResultsType& result)
  338. {
  339. error_code err;
  340. diagnostics diag;
  341. execute(std::forward<ExecutionRequest>(req), result, err, diag);
  342. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  343. }
  344. /// \copydoc any_connection::async_execute
  345. template <
  346. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  347. BOOST_MYSQL_RESULTS_TYPE ResultsType,
  348. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  349. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  350. auto async_execute(
  351. ExecutionRequest&& req,
  352. ResultsType& result,
  353. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  354. ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t<ExecutionRequest&&, ResultsType, CompletionToken&&>)
  355. {
  356. return async_execute(
  357. std::forward<ExecutionRequest>(req),
  358. result,
  359. impl_.shared_diag(),
  360. std::forward<CompletionToken>(token)
  361. );
  362. }
  363. /// \copydoc async_execute
  364. template <
  365. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  366. BOOST_MYSQL_RESULTS_TYPE ResultsType,
  367. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  368. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  369. auto async_execute(
  370. ExecutionRequest&& req,
  371. ResultsType& result,
  372. diagnostics& diag,
  373. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  374. ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t<ExecutionRequest&&, ResultsType, CompletionToken&&>)
  375. {
  376. return impl_.async_execute(
  377. std::forward<ExecutionRequest>(req),
  378. result,
  379. diag,
  380. std::forward<CompletionToken>(token)
  381. );
  382. }
  383. /// \copydoc any_connection::start_execution
  384. template <
  385. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  386. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType>
  387. void start_execution(ExecutionRequest&& req, ExecutionStateType& st, error_code& err, diagnostics& diag)
  388. {
  389. impl_.start_execution(std::forward<ExecutionRequest>(req), st, err, diag);
  390. }
  391. /// \copydoc start_execution
  392. template <
  393. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  394. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType>
  395. void start_execution(ExecutionRequest&& req, ExecutionStateType& st)
  396. {
  397. error_code err;
  398. diagnostics diag;
  399. start_execution(std::forward<ExecutionRequest>(req), st, err, diag);
  400. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  401. }
  402. /// \copydoc any_connection::async_start_execution
  403. template <
  404. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  405. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType,
  406. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  407. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  408. auto async_start_execution(
  409. ExecutionRequest&& req,
  410. ExecutionStateType& st,
  411. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  412. )
  413. BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t<
  414. ExecutionRequest&&,
  415. ExecutionStateType,
  416. CompletionToken&&>)
  417. {
  418. return async_start_execution(
  419. std::forward<ExecutionRequest>(req),
  420. st,
  421. impl_.shared_diag(),
  422. std::forward<CompletionToken>(token)
  423. );
  424. }
  425. /// \copydoc async_start_execution
  426. template <
  427. BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest,
  428. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType,
  429. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  430. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  431. auto async_start_execution(
  432. ExecutionRequest&& req,
  433. ExecutionStateType& st,
  434. diagnostics& diag,
  435. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  436. )
  437. BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t<
  438. ExecutionRequest&&,
  439. ExecutionStateType,
  440. CompletionToken&&>)
  441. {
  442. return impl_.async_start_execution(
  443. std::forward<ExecutionRequest>(req),
  444. st,
  445. diag,
  446. std::forward<CompletionToken>(token)
  447. );
  448. }
  449. /// \copydoc any_connection::prepare_statement
  450. statement prepare_statement(string_view stmt, error_code& err, diagnostics& diag)
  451. {
  452. return impl_.run(detail::prepare_statement_algo_params{stmt}, err, diag);
  453. }
  454. /// \copydoc prepare_statement
  455. statement prepare_statement(string_view stmt)
  456. {
  457. error_code err;
  458. diagnostics diag;
  459. statement res = prepare_statement(stmt, err, diag);
  460. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  461. return res;
  462. }
  463. /// \copydoc any_connection::async_prepare_statement
  464. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement))
  465. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  466. auto async_prepare_statement(
  467. string_view stmt,
  468. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  469. ) BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t<CompletionToken&&>)
  470. {
  471. return async_prepare_statement(stmt, impl_.shared_diag(), std::forward<CompletionToken>(token));
  472. }
  473. /// \copydoc async_prepare_statement
  474. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement))
  475. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  476. auto async_prepare_statement(
  477. string_view stmt,
  478. diagnostics& diag,
  479. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  480. ) BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t<CompletionToken&&>)
  481. {
  482. return impl_.async_run(
  483. detail::prepare_statement_algo_params{stmt},
  484. diag,
  485. std::forward<CompletionToken>(token)
  486. );
  487. }
  488. /// \copydoc any_connection::close_statement
  489. void close_statement(const statement& stmt, error_code& err, diagnostics& diag)
  490. {
  491. impl_.run(impl_.make_params_close_statement(stmt), err, diag);
  492. }
  493. /// \copydoc close_statement
  494. void close_statement(const statement& stmt)
  495. {
  496. error_code err;
  497. diagnostics diag;
  498. close_statement(stmt, err, diag);
  499. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  500. }
  501. /// \copydoc any_connection::async_close_statement
  502. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  503. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  504. auto async_close_statement(
  505. const statement& stmt,
  506. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  507. ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t<CompletionToken&&>)
  508. {
  509. return async_close_statement(stmt, impl_.shared_diag(), std::forward<CompletionToken>(token));
  510. }
  511. /// \copydoc async_close_statement
  512. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  513. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  514. auto async_close_statement(
  515. const statement& stmt,
  516. diagnostics& diag,
  517. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  518. ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t<CompletionToken&&>)
  519. {
  520. return impl_
  521. .async_run(impl_.make_params_close_statement(stmt), diag, std::forward<CompletionToken>(token));
  522. }
  523. /// \copydoc any_connection::read_some_rows
  524. rows_view read_some_rows(execution_state& st, error_code& err, diagnostics& diag)
  525. {
  526. return impl_.run(impl_.make_params_read_some_rows(st), err, diag);
  527. }
  528. /// \copydoc read_some_rows(execution_state&,error_code&,diagnostics&)
  529. rows_view read_some_rows(execution_state& st)
  530. {
  531. error_code err;
  532. diagnostics diag;
  533. rows_view res = read_some_rows(st, err, diag);
  534. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  535. return res;
  536. }
  537. /// \copydoc any_connection::async_read_some_rows(execution_state&,CompletionToken&&)
  538. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
  539. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  540. auto async_read_some_rows(
  541. execution_state& st,
  542. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  543. ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t<CompletionToken&&>)
  544. {
  545. return async_read_some_rows(st, impl_.shared_diag(), std::forward<CompletionToken>(token));
  546. }
  547. /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&)
  548. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
  549. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  550. auto async_read_some_rows(
  551. execution_state& st,
  552. diagnostics& diag,
  553. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  554. ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t<CompletionToken&&>)
  555. {
  556. return impl_
  557. .async_run(impl_.make_params_read_some_rows(st), diag, std::forward<CompletionToken>(token));
  558. }
  559. #ifdef BOOST_MYSQL_CXX14
  560. /**
  561. * \brief Reads a batch of rows.
  562. * \details
  563. * Reads a batch of rows of unspecified size into the storage given by `output`.
  564. * At most `output.size()` rows will be read. If the operation represented by `st`
  565. * has still rows to read, and `output.size() > 0`, at least one row will be read.
  566. * \n
  567. * Returns the number of read rows.
  568. * \n
  569. * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns
  570. * zero.
  571. * \n
  572. * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer,
  573. * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s
  574. * constructor, using \ref buffer_params::initial_read_size. The buffer may be
  575. * grown bigger by other read operations, if required.
  576. * \n
  577. * Rows read by this function are owning objects, and don't hold any reference to
  578. * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart).
  579. * \n
  580. * The type `SpanElementType` must be the underlying row type for one of the types in the
  581. * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`).
  582. * The type must match the resultset that is currently being processed by `st`. For instance,
  583. * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType`
  584. * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued.
  585. * \n
  586. * This function can report schema mismatches.
  587. */
  588. template <class SpanElementType, class... StaticRow>
  589. std::size_t read_some_rows(
  590. static_execution_state<StaticRow...>& st,
  591. span<SpanElementType> output,
  592. error_code& err,
  593. diagnostics& diag
  594. )
  595. {
  596. return impl_.run(impl_.make_params_read_some_rows_static(st, output), err, diag);
  597. }
  598. /**
  599. * \brief Reads a batch of rows.
  600. * \details
  601. * Reads a batch of rows of unspecified size into the storage given by `output`.
  602. * At most `output.size()` rows will be read. If the operation represented by `st`
  603. * has still rows to read, and `output.size() > 0`, at least one row will be read.
  604. * \n
  605. * Returns the number of read rows.
  606. * \n
  607. * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns
  608. * zero.
  609. * \n
  610. * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer,
  611. * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s
  612. * constructor, using \ref buffer_params::initial_read_size. The buffer may be
  613. * grown bigger by other read operations, if required.
  614. * \n
  615. * Rows read by this function are owning objects, and don't hold any reference to
  616. * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart).
  617. * \n
  618. * The type `SpanElementType` must be the underlying row type for one of the types in the
  619. * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`).
  620. * The type must match the resultset that is currently being processed by `st`. For instance,
  621. * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType`
  622. * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued.
  623. * \n
  624. * This function can report schema mismatches.
  625. */
  626. template <class SpanElementType, class... StaticRow>
  627. std::size_t read_some_rows(static_execution_state<StaticRow...>& st, span<SpanElementType> output)
  628. {
  629. error_code err;
  630. diagnostics diag;
  631. std::size_t res = read_some_rows(st, output, err, diag);
  632. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  633. return res;
  634. }
  635. /**
  636. * \brief Reads a batch of rows.
  637. * \details
  638. * Reads a batch of rows of unspecified size into the storage given by `output`.
  639. * At most `output.size()` rows will be read. If the operation represented by `st`
  640. * has still rows to read, and `output.size() > 0`, at least one row will be read.
  641. * \n
  642. * Returns the number of read rows.
  643. * \n
  644. * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns
  645. * zero.
  646. * \n
  647. * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer,
  648. * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s
  649. * constructor, using \ref buffer_params::initial_read_size. The buffer may be
  650. * grown bigger by other read operations, if required.
  651. * \n
  652. * Rows read by this function are owning objects, and don't hold any reference to
  653. * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart).
  654. * \n
  655. * The type `SpanElementType` must be the underlying row type for one of the types in the
  656. * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`).
  657. * The type must match the resultset that is currently being processed by `st`. For instance,
  658. * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType`
  659. * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued.
  660. * \n
  661. * This function can report schema mismatches.
  662. *
  663. * \par Handler signature
  664. * The handler signature for this operation is
  665. * `void(boost::mysql::error_code, std::size_t)`.
  666. *
  667. * \par Executor
  668. * Intermediate completion handlers, as well as the final handler, are executed using
  669. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  670. * executor.
  671. *
  672. * If the final handler has an associated immediate executor, and the operation
  673. * completes immediately, the final handler is dispatched to it.
  674. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  675. * and is never be called inline from within this function.
  676. *
  677. * \par Object lifetimes
  678. * The storage that `output` references must be kept alive until the operation completes.
  679. */
  680. template <
  681. class SpanElementType,
  682. class... StaticRow,
  683. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t))
  684. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  685. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t))
  686. async_read_some_rows(
  687. static_execution_state<StaticRow...>& st,
  688. span<SpanElementType> output,
  689. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  690. )
  691. {
  692. return async_read_some_rows(st, output, impl_.shared_diag(), std::forward<CompletionToken>(token));
  693. }
  694. /**
  695. * \brief Reads a batch of rows.
  696. * \details
  697. * Reads a batch of rows of unspecified size into the storage given by `output`.
  698. * At most `output.size()` rows will be read. If the operation represented by `st`
  699. * has still rows to read, and `output.size() > 0`, at least one row will be read.
  700. * \n
  701. * Returns the number of read rows.
  702. * \n
  703. * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns
  704. * zero.
  705. * \n
  706. * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer,
  707. * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s
  708. * constructor, using \ref buffer_params::initial_read_size. The buffer may be
  709. * grown bigger by other read operations, if required.
  710. * \n
  711. * Rows read by this function are owning objects, and don't hold any reference to
  712. * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart).
  713. * \n
  714. * The type `SpanElementType` must be the underlying row type for one of the types in the
  715. * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`).
  716. * The type must match the resultset that is currently being processed by `st`. For instance,
  717. * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType`
  718. * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued.
  719. * \n
  720. * This function can report schema mismatches.
  721. *
  722. * \par Handler signature
  723. * The handler signature for this operation is
  724. * `void(boost::mysql::error_code, std::size_t)`.
  725. *
  726. * \par Executor
  727. * Intermediate completion handlers, as well as the final handler, are executed using
  728. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  729. * executor.
  730. *
  731. * If the final handler has an associated immediate executor, and the operation
  732. * completes immediately, the final handler is dispatched to it.
  733. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  734. * and is never be called inline from within this function.
  735. *
  736. * \par Object lifetimes
  737. * The storage that `output` references must be kept alive until the operation completes.
  738. */
  739. template <
  740. class SpanElementType,
  741. class... StaticRow,
  742. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t))
  743. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  744. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t))
  745. async_read_some_rows(
  746. static_execution_state<StaticRow...>& st,
  747. span<SpanElementType> output,
  748. diagnostics& diag,
  749. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  750. )
  751. {
  752. return impl_.async_run(
  753. impl_.make_params_read_some_rows_static(st, output),
  754. diag,
  755. std::forward<CompletionToken>(token)
  756. );
  757. }
  758. #endif
  759. /// \copydoc any_connection::read_resultset_head
  760. template <BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType>
  761. void read_resultset_head(ExecutionStateType& st, error_code& err, diagnostics& diag)
  762. {
  763. return impl_.run(impl_.make_params_read_resultset_head(st), err, diag);
  764. }
  765. /// \copydoc read_resultset_head
  766. template <BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType>
  767. void read_resultset_head(ExecutionStateType& st)
  768. {
  769. error_code err;
  770. diagnostics diag;
  771. read_resultset_head(st, err, diag);
  772. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  773. }
  774. /// \copydoc any_connection::async_read_resultset_head
  775. template <
  776. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType,
  777. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  778. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  779. auto async_read_resultset_head(
  780. ExecutionStateType& st,
  781. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  782. ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t<CompletionToken&&>)
  783. {
  784. return async_read_resultset_head(st, impl_.shared_diag(), std::forward<CompletionToken>(token));
  785. }
  786. /// \copydoc async_read_resultset_head
  787. template <
  788. BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType,
  789. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  790. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  791. auto async_read_resultset_head(
  792. ExecutionStateType& st,
  793. diagnostics& diag,
  794. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  795. ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t<CompletionToken&&>)
  796. {
  797. return impl_
  798. .async_run(impl_.make_params_read_resultset_head(st), diag, std::forward<CompletionToken>(token));
  799. }
  800. /// \copydoc any_connection::ping
  801. void ping(error_code& err, diagnostics& diag) { impl_.run(detail::ping_algo_params{}, err, diag); }
  802. /// \copydoc ping
  803. void ping()
  804. {
  805. error_code err;
  806. diagnostics diag;
  807. ping(err, diag);
  808. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  809. }
  810. /// \copydoc any_connection::async_ping
  811. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  812. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  813. auto async_ping(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  814. BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t<CompletionToken&&>)
  815. {
  816. return async_ping(impl_.shared_diag(), std::forward<CompletionToken>(token));
  817. }
  818. /// \copydoc async_ping
  819. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  820. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  821. auto async_ping(
  822. diagnostics& diag,
  823. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  824. ) BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t<CompletionToken&&>)
  825. {
  826. return impl_.async_run(detail::ping_algo_params{}, diag, std::forward<CompletionToken>(token));
  827. }
  828. /**
  829. * \brief Resets server-side session state, like variables and prepared statements.
  830. * \details
  831. * Resets all server-side state for the current session:
  832. * \n
  833. * \li Rolls back any active transactions and resets autocommit mode.
  834. * \li Releases all table locks.
  835. * \li Drops all temporary tables.
  836. * \li Resets all session system variables to their default values (including the ones set by `SET
  837. * NAMES`) and clears all user-defined variables.
  838. * \li Closes all prepared statements.
  839. * \n
  840. * A full reference on the affected session state can be found
  841. * <a href="https://dev.mysql.com/doc/c-api/8.0/en/mysql-reset-connection.html">here</a>.
  842. * \n
  843. * This function will not reset the current physical connection and won't cause re-authentication.
  844. * It is faster than closing and re-opening a connection.
  845. * \n
  846. * The connection must be connected and authenticated before calling this function.
  847. * This function involves communication with the server, and thus may fail.
  848. *
  849. * \par Warning on character sets
  850. * This function will restore the connection's character set and collation **to the server's default**,
  851. * and not to the one specified during connection establishment. Some servers have `latin1` as their
  852. * default character set, which is not usually what you want. Use a `SET NAMES` statement after using
  853. * this function to be sure.
  854. * \n
  855. * You can find the character set that your server will use after reset by running:
  856. * \code
  857. * "SELECT @@global.character_set_client, @@global.character_set_results;"
  858. * \endcode
  859. */
  860. void reset_connection(error_code& err, diagnostics& diag)
  861. {
  862. impl_.run(detail::reset_connection_algo_params{}, err, diag);
  863. }
  864. /// \copydoc reset_connection
  865. void reset_connection()
  866. {
  867. error_code err;
  868. diagnostics diag;
  869. reset_connection(err, diag);
  870. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  871. }
  872. /**
  873. * \copydoc reset_connection
  874. * \details
  875. * \n
  876. * \par Handler signature
  877. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  878. *
  879. * \par Executor
  880. * Intermediate completion handlers, as well as the final handler, are executed using
  881. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  882. * executor.
  883. *
  884. * If the final handler has an associated immediate executor, and the operation
  885. * completes immediately, the final handler is dispatched to it.
  886. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  887. * and is never be called inline from within this function.
  888. */
  889. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  890. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  891. auto async_reset_connection(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  892. BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t<CompletionToken&&>)
  893. {
  894. return async_reset_connection(impl_.shared_diag(), std::forward<CompletionToken>(token));
  895. }
  896. /// \copydoc async_reset_connection
  897. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  898. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  899. auto async_reset_connection(
  900. diagnostics& diag,
  901. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  902. ) BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t<CompletionToken&&>)
  903. {
  904. return impl_
  905. .async_run(detail::reset_connection_algo_params{}, diag, std::forward<CompletionToken>(token));
  906. }
  907. /**
  908. * \brief Closes the connection to the server.
  909. * \details
  910. * This function is only available if `Stream` satisfies the `SocketStream` concept.
  911. * \n
  912. * Sends a quit request, performs the TLS shutdown (if required)
  913. * and closes the underlying stream. Prefer this function to \ref connection::quit.
  914. * \n
  915. */
  916. void close(error_code& err, diagnostics& diag)
  917. {
  918. static_assert(
  919. detail::is_socket_stream<Stream>::value,
  920. "close can only be used if Stream satisfies the SocketStream concept"
  921. );
  922. impl_.run(detail::close_connection_algo_params{}, err, diag);
  923. }
  924. /// \copydoc close
  925. void close()
  926. {
  927. static_assert(
  928. detail::is_socket_stream<Stream>::value,
  929. "close can only be used if Stream satisfies the SocketStream concept"
  930. );
  931. error_code err;
  932. diagnostics diag;
  933. close(err, diag);
  934. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  935. }
  936. /**
  937. * \copydoc close
  938. * \details
  939. * \par Handler signature
  940. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  941. *
  942. * \par Executor
  943. * Intermediate completion handlers, as well as the final handler, are executed using
  944. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  945. * executor.
  946. *
  947. * If the final handler has an associated immediate executor, and the operation
  948. * completes immediately, the final handler is dispatched to it.
  949. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  950. * and is never be called inline from within this function.
  951. */
  952. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  953. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  954. auto async_close(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  955. BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t<CompletionToken&&>)
  956. {
  957. static_assert(
  958. detail::is_socket_stream<Stream>::value,
  959. "async_close can only be used if Stream satisfies the SocketStream concept"
  960. );
  961. return async_close(impl_.shared_diag(), std::forward<CompletionToken>(token));
  962. }
  963. /// \copydoc async_close
  964. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  965. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  966. auto async_close(
  967. diagnostics& diag,
  968. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  969. ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t<CompletionToken&&>)
  970. {
  971. static_assert(
  972. detail::is_socket_stream<Stream>::value,
  973. "async_close can only be used if Stream satisfies the SocketStream concept"
  974. );
  975. return impl_
  976. .async_run(detail::close_connection_algo_params{}, diag, std::forward<CompletionToken>(token));
  977. }
  978. /**
  979. * \brief Notifies the MySQL server that the client wants to end the session and shutdowns SSL.
  980. * \details Sends a quit request to the MySQL server. If the connection is using SSL,
  981. * this function will also perform the SSL shutdown. You should
  982. * close the underlying physical connection after calling this function.
  983. * \n
  984. * If the `Stream` template parameter fulfills the `SocketConnection`
  985. * requirements, use \ref connection::close instead of this function,
  986. * as it also takes care of closing the underlying stream.
  987. */
  988. void quit(error_code& err, diagnostics& diag)
  989. {
  990. impl_.run(detail::quit_connection_algo_params{}, err, diag);
  991. }
  992. /// \copydoc quit
  993. void quit()
  994. {
  995. error_code err;
  996. diagnostics diag;
  997. quit(err, diag);
  998. detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION);
  999. }
  1000. /**
  1001. * \copydoc quit
  1002. * \details
  1003. * \par Handler signature
  1004. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  1005. *
  1006. * \par Executor
  1007. * Intermediate completion handlers, as well as the final handler, are executed using
  1008. * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated
  1009. * executor.
  1010. *
  1011. * If the final handler has an associated immediate executor, and the operation
  1012. * completes immediately, the final handler is dispatched to it.
  1013. * Otherwise, the final handler is called as if it was submitted using `asio::post`,
  1014. * and is never be called inline from within this function.
  1015. */
  1016. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  1017. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  1018. auto async_quit(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  1019. BOOST_MYSQL_RETURN_TYPE(detail::async_quit_connection_t<CompletionToken&&>)
  1020. {
  1021. return async_quit(impl_.shared_diag(), std::forward<CompletionToken>(token));
  1022. }
  1023. /// \copydoc async_quit
  1024. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  1025. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  1026. auto async_quit(
  1027. diagnostics& diag,
  1028. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  1029. ) BOOST_MYSQL_RETURN_TYPE(detail::async_quit_connection_t<CompletionToken&&>)
  1030. {
  1031. return impl_
  1032. .async_run(detail::quit_connection_algo_params{}, diag, std::forward<CompletionToken>(token));
  1033. }
  1034. /**
  1035. * \brief Rebinds the connection type to another executor.
  1036. * \details
  1037. * The `Stream` type must either provide a `rebind_executor`
  1038. * member with the same semantics, or be an instantiation of `boost::asio::ssl::stream` with
  1039. * a `Stream` type providing a `rebind_executor` member.
  1040. */
  1041. template <typename Executor1>
  1042. struct rebind_executor
  1043. {
  1044. /// The connection type when rebound to the specified executor.
  1045. using other = connection<typename detail::rebind_executor<Stream, Executor1>::type>;
  1046. };
  1047. };
  1048. } // namespace mysql
  1049. } // namespace boost
  1050. #endif