connection.hpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. //
  2. // Copyright (c) 2019-2023 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/diagnostics.hpp>
  11. #include <boost/mysql/error_code.hpp>
  12. #include <boost/mysql/execution_state.hpp>
  13. #include <boost/mysql/handshake_params.hpp>
  14. #include <boost/mysql/metadata_mode.hpp>
  15. #include <boost/mysql/results.hpp>
  16. #include <boost/mysql/row.hpp>
  17. #include <boost/mysql/row_view.hpp>
  18. #include <boost/mysql/rows.hpp>
  19. #include <boost/mysql/rows_view.hpp>
  20. #include <boost/mysql/statement.hpp>
  21. #include <boost/mysql/string_view.hpp>
  22. #include <boost/mysql/detail/auxiliar/access_fwd.hpp>
  23. #include <boost/mysql/detail/auxiliar/field_type_traits.hpp>
  24. #include <boost/mysql/detail/auxiliar/rebind_executor.hpp>
  25. #include <boost/mysql/detail/channel/channel.hpp>
  26. #include <boost/mysql/detail/protocol/protocol_types.hpp>
  27. #include <type_traits>
  28. #include <utility>
  29. /// The Boost libraries namespace.
  30. namespace boost {
  31. /// Boost.MySQL library namespace.
  32. namespace mysql {
  33. /**
  34. * \brief A connection to a MySQL server.
  35. * \details
  36. * Represents a connection to a MySQL server.
  37. *\n
  38. * `connection` is the main I/O object that this library implements. It owns a `Stream` object that
  39. * is accessed by functions involving network operations, as well as session state. You can access
  40. * the stream using \ref connection::stream, and its executor via \ref connection::get_executor. The
  41. * executor used by this object is always the same as the underlying stream.
  42. *\n
  43. * \par Thread safety
  44. * Distinct objects: safe. \n
  45. * Shared objects: unsafe. \n
  46. * This class is <b>not thread-safe</b>: for a single object, if you
  47. * call its member functions concurrently from separate threads, you will get a race condition.
  48. */
  49. template <class Stream>
  50. class connection
  51. {
  52. std::unique_ptr<detail::channel<Stream>> channel_;
  53. const detail::channel<Stream>& get_channel() const noexcept
  54. {
  55. assert(channel_ != nullptr);
  56. return *channel_;
  57. }
  58. diagnostics& shared_diag() noexcept { return get_channel().shared_diag(); }
  59. detail::channel<Stream>& get_channel() noexcept
  60. {
  61. assert(channel_ != nullptr);
  62. return *channel_;
  63. }
  64. #ifndef BOOST_MYSQL_DOXYGEN
  65. friend struct detail::connection_access;
  66. #endif
  67. public:
  68. /**
  69. * \brief Initializing constructor.
  70. * \details
  71. * As part of the initialization, an internal `Stream` object is created.
  72. *
  73. * \par Exception safety
  74. * Basic guarantee. Throws if the `Stream` constructor throws
  75. * or if memory allocation for internal state fails.
  76. *
  77. * \param args Arguments to be forwarded to the `Stream` constructor.
  78. */
  79. template <
  80. class... Args,
  81. class EnableIf = typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type>
  82. connection(Args&&... args) : connection(buffer_params(), std::forward<Args>(args)...)
  83. {
  84. }
  85. /**
  86. * \brief Initializing constructor with buffer params.
  87. * \details
  88. * As part of the initialization, an internal `Stream` object is created.
  89. *
  90. * \par Exception safety
  91. * Basic guarantee. Throws if the `Stream` constructor throws
  92. * or if memory allocation for internal state fails.
  93. *
  94. * \param buff_params Specifies initial sizes for internal buffers.
  95. * \param args Arguments to be forwarded to the `Stream` constructor.
  96. */
  97. template <
  98. class... Args,
  99. class EnableIf = typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type>
  100. connection(const buffer_params& buff_params, Args&&... args)
  101. : channel_(new detail::channel<Stream>(buff_params.initial_read_size(), std::forward<Args>(args)...))
  102. {
  103. }
  104. /**
  105. * \brief Move constructor.
  106. */
  107. connection(connection&& other) = default;
  108. /**
  109. * \brief Move assignment.
  110. */
  111. connection& operator=(connection&& rhs) = default;
  112. #ifndef BOOST_MYSQL_DOXYGEN
  113. connection(const connection&) = delete;
  114. connection& operator=(const connection&) = delete;
  115. #endif
  116. /// The executor type associated to this object.
  117. using executor_type = typename Stream::executor_type;
  118. /// Retrieves the executor associated to this object.
  119. executor_type get_executor() { return get_channel().get_executor(); }
  120. /// The `Stream` type this connection is using.
  121. using stream_type = Stream;
  122. /**
  123. * \brief Retrieves the underlying Stream object.
  124. * \details
  125. *
  126. * \par Exception safety
  127. * No-throw guarantee.
  128. */
  129. Stream& stream() noexcept { return get_channel().stream().next_layer(); }
  130. /**
  131. * \brief Retrieves the underlying Stream object.
  132. * \details
  133. *
  134. * \par Exception safety
  135. * No-throw guarantee.
  136. */
  137. const Stream& stream() const noexcept { return get_channel().stream().next_layer(); }
  138. /**
  139. * \brief Returns whether the connection negotiated the use of SSL or not.
  140. * \details
  141. * This function can be used to determine whether you are using a SSL
  142. * connection or not when using SSL negotiation.
  143. * \n
  144. * This function always returns `false` if the underlying
  145. * stream does not support SSL. This function always returns `false`
  146. * for connections that haven't been
  147. * established yet (handshake not run yet). If the handshake fails,
  148. * the return value is undefined.
  149. *
  150. * \par Exception safety
  151. * No-throw guarantee.
  152. *
  153. * \returns Whether the connection is using SSL.
  154. */
  155. bool uses_ssl() const noexcept { return get_channel().ssl_active(); }
  156. /**
  157. * \brief Returns the current metadata mode that this connection is using.
  158. * \details
  159. * \par Exception safety
  160. * No-throw guarantee.
  161. *
  162. * \returns The matadata mode that will be used for queries and statement executions.
  163. */
  164. metadata_mode meta_mode() const noexcept { return get_channel().meta_mode(); }
  165. /**
  166. * \brief Sets the metadata mode.
  167. * \details
  168. * Will affect any query and statement executions performed after the call.
  169. *
  170. * \par Exception safety
  171. * No-throw guarantee.
  172. *
  173. * \par Preconditions
  174. * No asynchronous operation should be outstanding when this function is called.
  175. *
  176. * \param v The new metadata mode.
  177. */
  178. void set_meta_mode(metadata_mode v) noexcept { get_channel().set_meta_mode(v); }
  179. /**
  180. * \brief Establishes a connection to a MySQL server.
  181. * \details
  182. * This function is only available if `Stream` satisfies the
  183. * `SocketStream` concept.
  184. * \n
  185. * Connects the underlying stream and performs the handshake
  186. * with the server. The underlying stream is closed in case of error. Prefer
  187. * this function to \ref connection::handshake.
  188. * \n
  189. * If using a SSL-capable stream, the SSL handshake will be performed by this function.
  190. * \n
  191. * `endpoint` should be convertible to `Stream::lowest_layer_type::endpoint_type`.
  192. */
  193. template <typename EndpointType>
  194. void connect(
  195. const EndpointType& endpoint,
  196. const handshake_params& params,
  197. error_code& ec,
  198. diagnostics& diag
  199. );
  200. /// \copydoc connect
  201. template <typename EndpointType>
  202. void connect(const EndpointType& endpoint, const handshake_params& params);
  203. /**
  204. * \copydoc connect
  205. * \par Object lifetimes
  206. * The strings pointed to by `params` should be kept alive by the caller
  207. * until the operation completes, as no copy is made by the library.
  208. * `endpoint` is copied as required and doesn't need to be kept alive.
  209. *
  210. * \par Handler signature
  211. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  212. */
  213. template <
  214. typename EndpointType,
  215. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  216. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  217. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  218. async_connect(
  219. const EndpointType& endpoint,
  220. const handshake_params& params,
  221. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  222. )
  223. {
  224. return async_connect(endpoint, params, this->shared_diag(), std::forward<CompletionToken>(token));
  225. }
  226. /// \copydoc async_connect
  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. diagnostics& diag,
  236. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  237. );
  238. /**
  239. * \brief Performs the MySQL-level handshake.
  240. * \details
  241. * Does not connect the underlying stream.
  242. * If the `Stream` template parameter fulfills the `SocketConnection`
  243. * requirements, use \ref connection::connect instead of this function.
  244. * \n
  245. * If using a SSL-capable stream, the SSL handshake will be performed by this function.
  246. */
  247. void handshake(const handshake_params& params, error_code& ec, diagnostics& diag);
  248. /// \copydoc handshake
  249. void handshake(const handshake_params& params);
  250. /**
  251. * \copydoc handshake
  252. * \par Object lifetimes
  253. * The strings pointed to by `params` should be kept alive by the caller
  254. * until the operation completes, as no copy is made by the library.
  255. *
  256. * \par Handler signature
  257. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  258. */
  259. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  260. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  261. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  262. async_handshake(
  263. const handshake_params& params,
  264. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  265. )
  266. {
  267. return async_handshake(params, shared_diag(), std::forward<CompletionToken>(token));
  268. }
  269. /// \copydoc async_handshake
  270. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  271. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  272. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  273. async_handshake(
  274. const handshake_params& params,
  275. diagnostics& diag,
  276. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  277. );
  278. /**
  279. * \brief Executes a SQL text query.
  280. * \details
  281. * Sends `query_string` to the server for execution and reads the response into `result`.
  282. * query_string should be encoded using the connection's character set.
  283. * \n
  284. * After this operation completes successfully, `result.has_value() == true`.
  285. * \n
  286. * Metadata in `result` will be populated according to `this->meta_mode()`.
  287. * \n
  288. * \par Security
  289. * If you compose `query_string` by concatenating strings manually, <b>your code is
  290. * vulnerable to SQL injection attacks</b>. If your query contains patameters unknown at
  291. * compile time, use prepared statements instead of this function.
  292. */
  293. void query(string_view query_string, results& result, error_code&, diagnostics&);
  294. /// \copydoc query
  295. void query(string_view query_string, results& result);
  296. /**
  297. * \copydoc query
  298. * \details
  299. * \par Object lifetimes
  300. * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the string
  301. * pointed to by `query_string` must be kept alive by the caller until the operation is
  302. * initiated.
  303. *
  304. * \par Handler signature
  305. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  306. */
  307. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  308. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  309. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  310. async_query(
  311. string_view query_string,
  312. results& result,
  313. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  314. )
  315. {
  316. return async_query(query_string, result, shared_diag(), std::forward<CompletionToken>(token));
  317. }
  318. /// \copydoc async_query
  319. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  320. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  321. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  322. async_query(
  323. string_view query_string,
  324. results& result,
  325. diagnostics& diag,
  326. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  327. );
  328. /**
  329. * \brief Starts a text query as a multi-function operation.
  330. * \details
  331. * Writes the query request and reads the initial server response and the column
  332. * metadata, but not the generated rows, if any. After this operation completes, `st` will have
  333. * \ref execution_state::meta populated, and may become \ref execution_state::complete
  334. * if the operation did not generate any rows (e.g. it was an `UPDATE`).
  335. * Metadata will be populated according to `this->meta_mode()`.
  336. * \n
  337. * If the operation generated any rows, these <b>must</b> be read (by using
  338. * \ref read_some_rows) before engaging in any further network operation.
  339. * Otherwise, the results are undefined.
  340. * \n
  341. * `query_string` should be encoded using the connection's character set.
  342. */
  343. void start_query(string_view query_string, execution_state& st, error_code&, diagnostics&);
  344. /// \copydoc start_query
  345. void start_query(string_view query_string, execution_state& st);
  346. /**
  347. * \copydoc start_query
  348. * \details
  349. * \par Object lifetimes
  350. * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the string
  351. * pointed to by `query_string` must be kept alive by the caller until the operation is
  352. * initiated.
  353. *
  354. * \par Handler signature
  355. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  356. */
  357. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  358. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  359. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  360. async_start_query(
  361. string_view query_string,
  362. execution_state& st,
  363. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  364. )
  365. {
  366. return async_start_query(query_string, st, shared_diag(), std::forward<CompletionToken>(token));
  367. }
  368. /// \copydoc async_start_query
  369. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  370. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  371. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  372. async_start_query(
  373. string_view query_string,
  374. execution_state& st,
  375. diagnostics& diag,
  376. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  377. );
  378. /**
  379. * \brief Prepares a statement server-side.
  380. * \details
  381. * `stmt` should be encoded using the connection's character set.
  382. * \n
  383. * The returned statement has `valid() == true`.
  384. */
  385. statement prepare_statement(string_view stmt, error_code&, diagnostics&);
  386. /// \copydoc prepare_statement
  387. statement prepare_statement(string_view stmt);
  388. /**
  389. * \copydoc prepare_statement
  390. * \details
  391. * \par Object lifetimes
  392. * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the string
  393. * pointed to by `stmt` must be kept alive by the caller until the operation is
  394. * initiated.
  395. *
  396. * \par Handler signature
  397. * The handler signature for this operation is `void(boost::mysql::error_code, boost::mysql::statement)`.
  398. */
  399. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement))
  400. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  401. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement))
  402. async_prepare_statement(
  403. string_view stmt,
  404. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  405. )
  406. {
  407. return async_prepare_statement(stmt, shared_diag(), std::forward<CompletionToken>(token));
  408. }
  409. /// \copydoc async_prepare_statement
  410. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement))
  411. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  412. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement))
  413. async_prepare_statement(
  414. string_view stmt,
  415. diagnostics& diag,
  416. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  417. );
  418. /**
  419. * \brief Executes a prepared statement.
  420. * \details
  421. * Executes a statement with the given parameters and reads the response into `result`.
  422. * \n
  423. * After this operation completes successfully, `result.has_value() == true`.
  424. * \n
  425. * The statement actual parameters (`params`) are passed as a `std::tuple` of elements.
  426. * See the `FieldLikeTuple` concept defition for more info. You should pass exactly as many
  427. * parameters as `this->num_params()`, or the operation will fail with an error.
  428. * String parameters should be encoded using the connection's character set.
  429. * \n
  430. * Metadata in `result` will be populated according to `conn.meta_mode()`, where `conn`
  431. * is the connection that prepared this statement.
  432. *
  433. * \par Preconditions
  434. * `stmt.valid() == true`
  435. */
  436. template <
  437. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  438. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  439. void execute_statement(
  440. const statement& stmt,
  441. const FieldLikeTuple& params,
  442. results& result,
  443. error_code& err,
  444. diagnostics& diag
  445. );
  446. /// \copydoc execute_statement
  447. template <
  448. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  449. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  450. void execute_statement(const statement& stmt, const FieldLikeTuple& params, results& result);
  451. /**
  452. * \copydoc execute_statement
  453. * \par Object lifetimes
  454. * If `CompletionToken` is deferred (like `use_awaitable`), and `params` contains any reference
  455. * type (like `string_view`), the caller must keep the values pointed by these references alive
  456. * until the operation is initiated. Value types will be copied/moved as required, so don't need
  457. * to be kept alive. It's not required to keep `stmt` alive, either.
  458. *
  459. * \par Handler signature
  460. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  461. */
  462. template <
  463. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  464. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  465. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type),
  466. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  467. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  468. async_execute_statement(
  469. const statement& stmt,
  470. FieldLikeTuple&& params,
  471. results& result,
  472. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  473. )
  474. {
  475. return async_execute_statement(
  476. stmt,
  477. std::forward<FieldLikeTuple>(params),
  478. result,
  479. shared_diag(),
  480. std::forward<CompletionToken>(token)
  481. );
  482. }
  483. /// \copydoc async_execute_statement
  484. template <
  485. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  486. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  487. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type),
  488. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  489. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  490. async_execute_statement(
  491. const statement& stmt,
  492. FieldLikeTuple&& params,
  493. results& result,
  494. diagnostics& diag,
  495. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  496. );
  497. /**
  498. * \brief Starts a statement execution as a multi-function operation.
  499. * \details
  500. * Writes the execute request and reads the initial server response and the column
  501. * metadata, but not the generated rows, if any. After this operation completes, `st` will have
  502. * \ref execution_state::meta populated, and may become \ref execution_state::complete
  503. * if the operation did not generate any rows (e.g. it was an `UPDATE`).
  504. * Metadata will be populated according to `this->meta_mode()`.
  505. * \n
  506. * If the operation generated any rows, these <b>must</b> be read (by using
  507. * \ref read_some_rows) before engaging in any further
  508. * operation involving server communication. Otherwise, the results are undefined.
  509. * \n
  510. * The statement actual parameters (`params`) are passed as a `std::tuple` of elements.
  511. * String parameters should be encoded using the connection's character set.
  512. *
  513. * \par Preconditions
  514. * `stmt.valid() == true`
  515. */
  516. template <
  517. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  518. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  519. void start_statement_execution(
  520. const statement& stmt,
  521. const FieldLikeTuple& params,
  522. execution_state& ex,
  523. error_code& err,
  524. diagnostics& diag
  525. );
  526. /// \copydoc start_statement_execution(const statement&,const FieldLikeTuple&,execution_state&,error_code&,diagnostics&)
  527. template <
  528. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  529. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  530. void start_statement_execution(const statement& stmt, const FieldLikeTuple& params, execution_state& st);
  531. /**
  532. * \copydoc start_statement_execution(const statement&,const FieldLikeTuple&,execution_state&,error_code&,diagnostics&)
  533. * \details
  534. * \par Object lifetimes
  535. * If `CompletionToken` is deferred (like `use_awaitable`), and `params` contains any reference
  536. * type (like `string_view`), the caller must keep the values pointed by these references alive
  537. * until the operation is initiated. Value types will be copied/moved as required, so don't need
  538. * to be kept alive. It's not required to keep `stmt` alive, either.
  539. *
  540. * \par Handler signature
  541. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  542. */
  543. template <
  544. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  545. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  546. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type),
  547. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  548. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  549. async_start_statement_execution(
  550. const statement& stmt,
  551. FieldLikeTuple&& params,
  552. execution_state& st,
  553. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  554. )
  555. {
  556. return async_start_statement_execution(
  557. stmt,
  558. std::forward<FieldLikeTuple>(params),
  559. st,
  560. get_channel().shared_diag(),
  561. std::forward<CompletionToken>(token)
  562. );
  563. }
  564. /// \copydoc async_start_statement_execution(const statement&,FieldLikeTuple&&,execution_state&,CompletionToken&&)
  565. template <
  566. BOOST_MYSQL_FIELD_LIKE_TUPLE FieldLikeTuple,
  567. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  568. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type),
  569. class EnableIf = detail::enable_if_field_like_tuple<FieldLikeTuple>>
  570. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  571. async_start_statement_execution(
  572. const statement& stmt,
  573. FieldLikeTuple&& params,
  574. execution_state& st,
  575. diagnostics& diag,
  576. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  577. );
  578. /**
  579. * \brief Starts a statement execution as a multi-function operation.
  580. * \details
  581. * Writes the execute request and reads the initial server response and the column
  582. * metadata, but not the generated rows, if any. After this operation completes, `st` will have
  583. * \ref execution_state::meta populated, and may become \ref execution_state::complete
  584. * if the operation did not generate any rows (e.g. it was an `UPDATE`).
  585. * \n
  586. * If the operation generated any rows, these <b>must</b> be read (by using
  587. * \ref connection::read_some_rows) before engaging in any further
  588. * operation involving server communication. Otherwise, the results are undefined.
  589. * \n
  590. * The statement actual parameters are passed as an iterator range.
  591. * String parameters should be encoded using the connection's character set.
  592. *
  593. * \par Preconditions
  594. * `stmt.valid() == true`
  595. */
  596. template <BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator>
  597. void start_statement_execution(
  598. const statement& stmt,
  599. FieldViewFwdIterator params_first,
  600. FieldViewFwdIterator params_last,
  601. execution_state& st,
  602. error_code& ec,
  603. diagnostics& diag
  604. );
  605. /// \copydoc start_statement_execution(const statement&,FieldViewFwdIterator,FieldViewFwdIterator,execution_state&,error_code&,diagnostics&)
  606. template <BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator>
  607. void start_statement_execution(
  608. const statement& stmt,
  609. FieldViewFwdIterator params_first,
  610. FieldViewFwdIterator params_last,
  611. execution_state& st
  612. );
  613. /**
  614. * \copydoc start_statement_execution(const statement&,FieldViewFwdIterator,FieldViewFwdIterator,execution_state&,error_code&,diagnostics&)
  615. * \details
  616. * \par Object lifetimes
  617. * If `CompletionToken` is deferred (like `use_awaitable`), the caller must keep objects in
  618. * the iterator range alive until the operation is initiated.
  619. *
  620. * \par Handler signature
  621. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  622. */
  623. template <
  624. BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator,
  625. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  626. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  627. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  628. async_start_statement_execution(
  629. const statement& stmt,
  630. FieldViewFwdIterator params_first,
  631. FieldViewFwdIterator params_last,
  632. execution_state& st,
  633. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  634. )
  635. {
  636. return async_start_statement_execution(
  637. stmt,
  638. params_first,
  639. params_last,
  640. st,
  641. get_channel().shared_diag(),
  642. std::forward<CompletionToken>(token)
  643. );
  644. }
  645. /// \copydoc async_start_statement_execution(const statement&,FieldViewFwdIterator,FieldViewFwdIterator,execution_state&,CompletionToken&&)
  646. template <
  647. BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator,
  648. BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  649. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  650. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  651. async_start_statement_execution(
  652. const statement& stmt,
  653. FieldViewFwdIterator params_first,
  654. FieldViewFwdIterator params_last,
  655. execution_state& st,
  656. diagnostics& diag,
  657. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  658. );
  659. /**
  660. * \brief Closes a statement, deallocating it from the server.
  661. * \details
  662. * After this operation succeeds, `stmt` must not be used again for execution.
  663. * \n
  664. * \par Preconditions
  665. * `stmt.valid() == true`
  666. */
  667. void close_statement(const statement& stmt, error_code&, diagnostics&);
  668. /// \copydoc close_statement
  669. void close_statement(const statement& stmt);
  670. /**
  671. * \copydoc close_statement
  672. * \details
  673. * \par Object lifetimes
  674. * It is not required to keep `stmt` alive, as copies are made by the implementation as required.
  675. *
  676. * \par Handler signature
  677. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  678. */
  679. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  680. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  681. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  682. async_close_statement(
  683. const statement& stmt,
  684. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  685. )
  686. {
  687. return async_close_statement(stmt, shared_diag(), std::forward<CompletionToken>(token));
  688. }
  689. /// \copydoc async_close_statement
  690. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  691. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  692. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  693. async_close_statement(
  694. const statement& stmt,
  695. diagnostics& diag,
  696. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  697. );
  698. /**
  699. * \brief Reads a batch of rows.
  700. * \details
  701. * The number of rows that will be read is unspecified. If the resultset being read
  702. * has still rows to read, at least one will be read. If there are no more
  703. * rows to be read, returns an empty `rows_view`.
  704. * \n
  705. * The number of rows that will be read depends on the input buffer size. The bigger the buffer,
  706. * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s
  707. * constructor, using \ref buffer_params::initial_read_size. The buffer may be
  708. * grown bigger by other read operations, if required.
  709. * \n
  710. * The returned view points into memory owned by `*this`. It will be valid until
  711. * `*this` performs the next network operation or is destroyed.
  712. */
  713. rows_view read_some_rows(execution_state& st, error_code& err, diagnostics& info);
  714. /// \copydoc read_some_rows
  715. rows_view read_some_rows(execution_state& st);
  716. /**
  717. * \copydoc read_some_rows
  718. * \details
  719. * \par Handler signature
  720. * The handler signature for this operation is
  721. * `void(boost::mysql::error_code, boost::mysql::rows_view)`.
  722. */
  723. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
  724. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  725. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
  726. async_read_some_rows(
  727. execution_state& st,
  728. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  729. )
  730. {
  731. return async_read_some_rows(st, shared_diag(), std::forward<CompletionToken>(token));
  732. }
  733. /// \copydoc async_read_some_rows
  734. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
  735. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  736. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
  737. async_read_some_rows(
  738. execution_state& st,
  739. diagnostics& diag,
  740. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  741. );
  742. /**
  743. * \brief Checks whether the server is alive.
  744. * \details
  745. * If the server is alive, this function will complete without error.
  746. * If it's not, it will fail with the relevant network or protocol error.
  747. * \n
  748. * Note that ping requests are treated as any other type of request at the protocol
  749. * level, and won't be prioritized anyhow by the server. If the server is stuck
  750. * in a long-running query, the ping request won't be answered until the query is
  751. * finished.
  752. */
  753. void ping(error_code&, diagnostics&);
  754. /// \copydoc ping
  755. void ping();
  756. /**
  757. * \copydoc ping
  758. * \details
  759. * \n
  760. * \par Handler signature
  761. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  762. */
  763. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  764. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  765. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  766. async_ping(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  767. {
  768. return async_ping(this->shared_diag(), std::forward<CompletionToken>(token));
  769. }
  770. /// \copydoc async_ping
  771. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  772. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  773. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  774. async_ping(diagnostics& diag, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
  775. /**
  776. * \brief Closes the connection to the server.
  777. * \details
  778. * This function is only available if `Stream` satisfies the `SocketStream` concept.
  779. * \n
  780. * Sends a quit request, performs the TLS shutdown (if required)
  781. * and closes the underlying stream. Prefer this function to \ref connection::quit.
  782. */
  783. void close(error_code&, diagnostics&);
  784. /// \copydoc close
  785. void close();
  786. /**
  787. * \copydoc close
  788. * \details
  789. * \par Handler signature
  790. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  791. */
  792. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  793. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  794. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  795. async_close(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  796. {
  797. return async_close(this->shared_diag(), std::forward<CompletionToken>(token));
  798. }
  799. /// \copydoc async_close
  800. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  801. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  802. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  803. async_close(
  804. diagnostics& diag,
  805. CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
  806. );
  807. /**
  808. * \brief Notifies the MySQL server that the client wants to end the session and shutdowns SSL.
  809. * \details Sends a quit request to the MySQL server. If the connection is using SSL,
  810. * this function will also perform the SSL shutdown. You should
  811. * close the underlying physical connection after calling this function.
  812. * \n
  813. * If the `Stream` template parameter fulfills the `SocketConnection`
  814. * requirements, use \ref connection::close instead of this function,
  815. * as it also takes care of closing the underlying stream.
  816. */
  817. void quit(error_code&, diagnostics&);
  818. /// \copydoc quit
  819. void quit();
  820. /**
  821. * \copydoc quit
  822. * \details
  823. * \par Handler signature
  824. * The handler signature for this operation is `void(boost::mysql::error_code)`.
  825. */
  826. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  827. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  828. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  829. async_quit(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
  830. {
  831. return async_quit(shared_diag(), std::forward<CompletionToken>(token));
  832. }
  833. /// \copydoc async_quit
  834. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
  835. CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
  836. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  837. async_quit(diagnostics& diag, CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
  838. /**
  839. * \brief Rebinds the connection type to another executor.
  840. * \details
  841. * The `Stream` type must either provide a `rebind_executor`
  842. * member with the same semantics, or be an instantiation of `boost::asio::ssl::stream` with
  843. * a `Stream` type providing a `rebind_executor` member.
  844. */
  845. template <typename Executor1>
  846. struct rebind_executor
  847. {
  848. /// The connection type when rebound to the specified executor.
  849. using other = connection<typename detail::rebind_executor<Stream, Executor1>::type>;
  850. };
  851. };
  852. /// The default TCP port for the MySQL protocol.
  853. constexpr unsigned short default_port = 3306;
  854. /// The default TCP port for the MySQL protocol, as a string. Useful for hostname resolution.
  855. constexpr const char* default_port_string = "3306";
  856. } // namespace mysql
  857. } // namespace boost
  858. #include <boost/mysql/impl/connection.hpp>
  859. #endif