![]() |
|
|||
File indexing completed on 2025-09-15 08:42:59
0001 // 0002 // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 0008 #ifndef BOOST_MYSQL_ANY_CONNECTION_HPP 0009 #define BOOST_MYSQL_ANY_CONNECTION_HPP 0010 0011 #include <boost/mysql/any_address.hpp> 0012 #include <boost/mysql/character_set.hpp> 0013 #include <boost/mysql/connect_params.hpp> 0014 #include <boost/mysql/defaults.hpp> 0015 #include <boost/mysql/diagnostics.hpp> 0016 #include <boost/mysql/error_code.hpp> 0017 #include <boost/mysql/execution_state.hpp> 0018 #include <boost/mysql/metadata_mode.hpp> 0019 #include <boost/mysql/rows_view.hpp> 0020 #include <boost/mysql/statement.hpp> 0021 #include <boost/mysql/string_view.hpp> 0022 #include <boost/mysql/with_diagnostics.hpp> 0023 0024 #include <boost/mysql/detail/access.hpp> 0025 #include <boost/mysql/detail/algo_params.hpp> 0026 #include <boost/mysql/detail/config.hpp> 0027 #include <boost/mysql/detail/connect_params_helpers.hpp> 0028 #include <boost/mysql/detail/connection_impl.hpp> 0029 #include <boost/mysql/detail/engine.hpp> 0030 #include <boost/mysql/detail/execution_concepts.hpp> 0031 #include <boost/mysql/detail/ssl_fwd.hpp> 0032 #include <boost/mysql/detail/throw_on_error_loc.hpp> 0033 0034 #include <boost/asio/any_io_executor.hpp> 0035 #include <boost/asio/deferred.hpp> 0036 #include <boost/assert.hpp> 0037 #include <boost/optional/optional.hpp> 0038 #include <boost/system/result.hpp> 0039 0040 #include <cstddef> 0041 #include <cstdint> 0042 #include <memory> 0043 #include <type_traits> 0044 #include <utility> 0045 #include <vector> 0046 0047 namespace boost { 0048 namespace mysql { 0049 0050 // Forward declarations 0051 template <class... StaticRow> 0052 class static_execution_state; 0053 0054 class pipeline_request; 0055 class stage_response; 0056 0057 /** 0058 * \brief Configuration parameters that can be passed to \ref any_connection's constructor. 0059 */ 0060 struct any_connection_params 0061 { 0062 /** 0063 * \brief An external SSL context containing options to configure TLS. 0064 * \details 0065 * Relevant only for SSL connections (those that result on \ref 0066 * any_connection::uses_ssl returning `true`). 0067 * \n 0068 * If the connection is configured to use TLS, an internal `asio::ssl::stream` 0069 * object will be created. If this member is set to a non-null value, 0070 * this internal object will be initialized using the passed context. 0071 * This is the only way to configure TLS options in `any_connection`. 0072 * \n 0073 * If the connection is configured to use TLS and this member is `nullptr`, 0074 * an internal `asio::ssl::context` object with suitable default options 0075 * will be created. 0076 * 0077 * \par Object lifetimes 0078 * If set to non-null, the pointee object must be kept alive until 0079 * all \ref any_connection objects constructed from `*this` are destroyed. 0080 */ 0081 asio::ssl::context* ssl_context{}; 0082 0083 /** 0084 * \brief The initial size of the connection's buffer, in bytes. 0085 * \details A bigger read buffer can increase the number of rows 0086 * returned by \ref any_connection::read_some_rows. 0087 */ 0088 std::size_t initial_buffer_size{default_initial_read_buffer_size}; 0089 0090 /** 0091 * \brief The maximum size of the connection's buffer, in bytes (64MB by default). 0092 * \details 0093 * Attempting to read or write a protocol packet bigger than this size 0094 * will fail with a \ref client_errc::max_buffer_size_exceeded error. 0095 * \n 0096 * This effectively means: \n 0097 * - Each request sent to the server must be smaller than this value. 0098 * - Each individual row received from the server must be smaller than this value. 0099 * Note that when using `execute` or `async_execute`, results objects may 0100 * allocate memory beyond this limit if the total number of rows is high. 0101 * \n 0102 * If you need to send or receive larger packets, you may need to adjust 0103 * your server's <a 0104 * href="https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_max_allowed_packet">`max_allowed_packet`</a> 0105 * system variable, too. 0106 */ 0107 std::size_t max_buffer_size{0x4000000}; 0108 }; 0109 0110 /** 0111 * \brief A connection to a MySQL server. 0112 * \details 0113 * Represents a connection to a MySQL server. 0114 * This is the main I/O object that this library implements. It's logically comprised 0115 * of session state and an internal stream (usually a socket). The stream is not directly 0116 * accessible. It's constructed using the executor passed to the constructor. 0117 * 0118 * This class supports establishing connections 0119 * with servers using TCP, TCP over TLS and UNIX sockets. 0120 * 0121 * The class is named `any_connection` because it's not templated on a `Stream` 0122 * type, as opposed to \ref connection. New code should prefer using `any_connection` 0123 * whenever possible. 0124 * 0125 * Compared to \ref connection, this class: 0126 * 0127 * - Is type-erased. The type of the connection doesn't depend on the transport being used. 0128 * - Is easier to connect, as \ref connect and \ref async_connect handle hostname resolution. 0129 * - Can always be re-connected after being used or encountering an error. 0130 * - Always uses `asio::any_io_executor`. 0131 * - Has the same level of performance. 0132 * 0133 * This is a move-only type. 0134 * 0135 * \par Single outstanding async operation per connection 0136 * At any given point in time, only one async operation can be outstanding 0137 * per connection. If an async operation is initiated while another one is in progress, 0138 * it will fail with \ref client_errc::operation_in_progress. 0139 * 0140 * \par Default completion tokens 0141 * The default completion token for all async operations in this class is 0142 * `with_diagnostics(asio::deferred)`, which allows you to use `co_await` 0143 * and have the expected exceptions thrown on error. 0144 * 0145 * \par Thread safety 0146 * Distinct objects: safe. \n 0147 * Shared objects: unsafe. \n 0148 * This class is <b>not thread-safe</b>: for a single object, if you 0149 * call its member functions concurrently from separate threads, you will get a race condition. 0150 */ 0151 class any_connection 0152 { 0153 detail::connection_impl impl_; 0154 0155 #ifndef BOOST_MYSQL_DOXYGEN 0156 friend struct detail::access; 0157 #endif 0158 0159 BOOST_MYSQL_DECL 0160 static std::unique_ptr<detail::engine> create_engine(asio::any_io_executor ex, asio::ssl::context* ctx); 0161 0162 // Used by tests 0163 any_connection(std::unique_ptr<detail::engine> eng, any_connection_params params) 0164 : impl_(params.initial_buffer_size, params.max_buffer_size, std::move(eng)) 0165 { 0166 } 0167 0168 public: 0169 /** 0170 * \brief Constructs a connection object from an executor and an optional set of parameters. 0171 * \details 0172 * The resulting connection has `this->get_executor() == ex`. Any internally required I/O objects 0173 * will be constructed using this executor. 0174 * \n 0175 * You can configure extra parameters, like the SSL context and buffer sizes, by passing 0176 * an \ref any_connection_params object to this constructor. 0177 */ 0178 any_connection(boost::asio::any_io_executor ex, any_connection_params params = {}) 0179 : any_connection(create_engine(std::move(ex), params.ssl_context), params) 0180 { 0181 } 0182 0183 /** 0184 * \brief Constructs a connection object from an execution context and an optional set of parameters. 0185 * \details 0186 * The resulting connection has `this->get_executor() == ctx.get_executor()`. 0187 * Any internally required I/O objects will be constructed using this executor. 0188 * \n 0189 * You can configure extra parameters, like the SSL context and buffer sizes, by passing 0190 * an \ref any_connection_params object to this constructor. 0191 * \n 0192 * This function participates in overload resolution only if `ExecutionContext` 0193 * satisfies the `ExecutionContext` requirements imposed by Boost.Asio. 0194 */ 0195 template < 0196 class ExecutionContext 0197 #ifndef BOOST_MYSQL_DOXYGEN 0198 , 0199 class = typename std::enable_if<std::is_convertible< 0200 decltype(std::declval<ExecutionContext&>().get_executor()), 0201 asio::any_io_executor>::value>::type 0202 #endif 0203 > 0204 any_connection(ExecutionContext& ctx, any_connection_params params = {}) 0205 : any_connection(ctx.get_executor(), params) 0206 { 0207 } 0208 0209 /** 0210 * \brief Move constructor. 0211 */ 0212 any_connection(any_connection&& other) = default; 0213 0214 /** 0215 * \brief Move assignment. 0216 */ 0217 any_connection& operator=(any_connection&& rhs) = default; 0218 0219 #ifndef BOOST_MYSQL_DOXYGEN 0220 any_connection(const any_connection&) = delete; 0221 any_connection& operator=(const any_connection&) = delete; 0222 #endif 0223 0224 /** 0225 * \brief Destructor. 0226 * \details 0227 * Closes the connection at the transport layer (by closing any underlying socket objects). 0228 * If you require a clean close, call \ref close or \ref async_close before the connection 0229 * is destroyed. 0230 */ 0231 ~any_connection() = default; 0232 0233 /// The executor type associated to this object. 0234 using executor_type = asio::any_io_executor; 0235 0236 /** 0237 * \brief Retrieves the executor associated to this object. 0238 * \par Exception safety 0239 * No-throw guarantee. 0240 */ 0241 executor_type get_executor() noexcept { return impl_.get_engine().get_executor(); } 0242 0243 /** 0244 * \brief Returns whether the connection negotiated the use of SSL or not. 0245 * \details 0246 * This function can be used to determine whether you are using a SSL 0247 * connection or not when using SSL negotiation. 0248 * \n 0249 * This function always returns `false` 0250 * for connections that haven't been established yet. If the connection establishment fails, 0251 * the return value is undefined. 0252 * 0253 * \par Exception safety 0254 * No-throw guarantee. 0255 */ 0256 bool uses_ssl() const noexcept { return impl_.ssl_active(); } 0257 0258 /** 0259 * \brief Returns whether backslashes are being treated as escape sequences. 0260 * \details 0261 * By default, the server treats backslashes in string values as escape characters. 0262 * This behavior can be disabled by activating the <a 0263 * href="https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_no_backslash_escapes">`NO_BACKSLASH_ESCAPES`</a> 0264 * SQL mode. 0265 * \n 0266 * Every time an operation involving server communication completes, the server reports whether 0267 * this mode was activated or not as part of the response. Connections store this information 0268 * and make it available through this function. 0269 * \n 0270 * \li If backslash are treated like escape characters, returns `true`. 0271 * \li If `NO_BACKSLASH_ESCAPES` has been activated, returns `false`. 0272 * \li If connection establishment hasn't happened yet, returns `true`. 0273 * \li Calling this function while an async operation that changes backslash behavior 0274 * is outstanding may return `true` or `false`. 0275 * \n 0276 * This function does not involve server communication. 0277 * 0278 * \par Exception safety 0279 * No-throw guarantee. 0280 */ 0281 bool backslash_escapes() const noexcept { return impl_.backslash_escapes(); } 0282 0283 /** 0284 * \brief Returns the character set used by this connection. 0285 * \details 0286 * Connections attempt to keep track of the current character set. 0287 * Deficiencies in the protocol can cause the character set to be unknown, though. 0288 * When the character set is known, this function returns 0289 * the character set currently in use. Otherwise, returns \ref client_errc::unknown_character_set. 0290 * \n 0291 * The following functions can modify the return value of this function: \n 0292 * \li Prior to connection, the character set is always unknown. 0293 * \li \ref connect and \ref async_connect may set the current character set 0294 * to a known value, depending on the requested collation. 0295 * \li \ref set_character_set always and \ref async_set_character_set always 0296 * set the current character set to the passed value. 0297 * \li \ref reset_connection and \ref async_reset_connection always makes the current character 0298 * unknown. 0299 * 0300 * \par Avoid changing the character set directly 0301 * If you change the connection's character set directly using SQL statements 0302 * like `"SET NAMES utf8mb4"`, the client has no way to track this change, 0303 * and this function will return incorrect results. 0304 * 0305 * \par Errors 0306 * \li \ref client_errc::unknown_character_set if the current character set is unknown. 0307 * 0308 * \par Exception safety 0309 * No-throw guarantee. 0310 */ 0311 system::result<character_set> current_character_set() const noexcept 0312 { 0313 return impl_.current_character_set(); 0314 } 0315 0316 /** 0317 * \brief Returns format options suitable to format SQL according to the current connection configuration. 0318 * \details 0319 * If the current character set is known (as given by \ref current_character_set), returns 0320 * a value suitable to be passed to SQL formatting functions. Otherwise, returns an error. 0321 * 0322 * \par Errors 0323 * \li \ref client_errc::unknown_character_set if the current character set is unknown. 0324 * 0325 * \par Exception safety 0326 * No-throw guarantee. 0327 */ 0328 system::result<format_options> format_opts() const noexcept 0329 { 0330 auto res = current_character_set(); 0331 if (res.has_error()) 0332 return res.error(); 0333 return format_options{res.value(), backslash_escapes()}; 0334 } 0335 0336 /** 0337 * \brief Returns the current metadata mode that this connection is using. 0338 * \details 0339 * \par Exception safety 0340 * No-throw guarantee. 0341 * 0342 * \returns The metadata mode that will be used for queries and statement executions. 0343 */ 0344 metadata_mode meta_mode() const noexcept { return impl_.meta_mode(); } 0345 0346 /** 0347 * \brief Sets the metadata mode. 0348 * \details 0349 * Will affect any query and statement executions performed after the call. 0350 * 0351 * \par Exception safety 0352 * No-throw guarantee. 0353 * 0354 * \par Preconditions 0355 * No asynchronous operation should be outstanding when this function is called. 0356 * 0357 * \param v The new metadata mode. 0358 */ 0359 void set_meta_mode(metadata_mode v) noexcept { impl_.set_meta_mode(v); } 0360 0361 /** 0362 * \brief Retrieves the connection id associated to the current session. 0363 * \details 0364 * If a session has been established, returns its associated connection id. 0365 * If no session has been established (i.e. \ref async_connect hasn't been called yet) 0366 * or the session has been terminated (i.e. \ref async_close has been called), an empty 0367 * optional is returned. 0368 * 0369 * The connection id is a 4 byte value that uniquely identifies a client session 0370 * at a given point in time. It can be used with the 0371 * <a href="https://dev.mysql.com/doc/refman/8.4/en/kill.html">`KILL`</a> SQL statement 0372 * to cancel queries and terminate connections. 0373 * 0374 * The server sends the connection id assigned to the current session as part of the 0375 * handshake process. The value is stored and made available through this function. 0376 * The same id can also be obtained by calling the 0377 * <a 0378 * href="https://dev.mysql.com/doc/refman/8.4/en/information-functions.html#function_connection-id">CONNECTION_ID()</a> 0379 * SQL function. However, this function is faster and more reliable, since it does not entail 0380 * communication with the server. 0381 * 0382 * This function is equivalent to the 0383 * <a href="https://dev.mysql.com/doc/c-api/8.0/en/mysql-thread-id.html">`mysql_thread_id`</a> function 0384 * in the C connector. This function works properly in 64-bit systems, as opposed to what 0385 * the official docs suggest (see 0386 * <a href="https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-5.html">this changelog</a>). 0387 * 0388 * It is safe to call this function while an async operation is outstanding, except for \ref async_connect 0389 * and \ref async_close. 0390 * 0391 * \par Exception safety 0392 * No-throw guarantee. 0393 */ 0394 boost::optional<std::uint32_t> connection_id() const noexcept { return impl_.connection_id(); } 0395 0396 /** 0397 * \brief Establishes a connection to a MySQL server. 0398 * \details 0399 * This function performs the following: 0400 * \n 0401 * \li If a connection has already been established (by a previous call to \ref connect 0402 * or \ref async_connect), closes it at the transport layer (by closing any underlying socket) 0403 * and discards any protocol state associated to it. (If you require 0404 * a clean close, call \ref close or \ref async_close before using this function). 0405 * \li If the connection is configured to use TCP (`params.server_address.type() == 0406 * address_type::host_and_port`), resolves the passed hostname to a set of endpoints. An empty 0407 * hostname is equivalent to `"localhost"`. 0408 * \li Establishes the physical connection (performing the 0409 * TCP or UNIX socket connect). 0410 * \li Performs the MySQL handshake to establish a session. If the 0411 * connection is configured to use TLS, the TLS handshake is performed as part of this step. 0412 * \li If any of the above steps fail, the TCP or UNIX socket connection is closed. 0413 * \n 0414 * You can configure some options using the \ref connect_params struct. 0415 * \n 0416 * The decision to use TLS or not is performed using the following: 0417 * \n 0418 * \li If the transport is not TCP (`params.server_address.type() != address_type::host_and_port`), 0419 * the connection will never use TLS. 0420 * \li If the transport is TCP, and `params.ssl == ssl_mode::disable`, the connection will not use TLS. 0421 * \li If the transport is TCP, and `params.ssl == ssl_mode::enable`, the connection will use TLS 0422 * only if the server supports it. 0423 * \li If the transport is TCP, and `params.ssl == ssl_mode::require`, the connection will always use TLS. 0424 * If the server doesn't support it, the operation will fail with \ref 0425 * client_errc::server_doesnt_support_ssl. 0426 * \n 0427 * If `params.connection_collation` is within a set of well-known collations, this function 0428 * sets the current character set, such that \ref current_character_set returns a non-null value. 0429 * The default collation (`utf8mb4_general_ci`) is the only one guaranteed to be in the set of well-known 0430 * collations. 0431 */ 0432 void connect(const connect_params& params, error_code& ec, diagnostics& diag) 0433 { 0434 impl_.connect_v2(params, ec, diag); 0435 } 0436 0437 /// \copydoc connect 0438 void connect(const connect_params& params) 0439 { 0440 error_code err; 0441 diagnostics diag; 0442 connect(params, err, diag); 0443 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0444 } 0445 0446 /** 0447 * \copydoc connect 0448 * 0449 * \par Object lifetimes 0450 * params needs to be kept alive until the operation completes, as no 0451 * copies will be made by the library. 0452 * 0453 * \par Handler signature 0454 * The handler signature for this operation is `void(boost::mysql::error_code)`. 0455 * 0456 * \par Executor 0457 * Intermediate completion handlers, as well as the final handler, are executed using 0458 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0459 * executor. 0460 * 0461 * If the final handler has an associated immediate executor, and the operation 0462 * completes immediately, the final handler is dispatched to it. 0463 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0464 * and is never be called inline from within this function. 0465 */ 0466 template < 0467 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 0468 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0469 auto async_connect(const connect_params& params, diagnostics& diag, CompletionToken&& token = {}) 0470 BOOST_MYSQL_RETURN_TYPE(detail::async_connect_v2_t<CompletionToken&&>) 0471 { 0472 return impl_.async_connect_v2(params, diag, std::forward<CompletionToken>(token)); 0473 } 0474 0475 /// \copydoc async_connect 0476 template < 0477 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 0478 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0479 auto async_connect(const connect_params& params, CompletionToken&& token = {}) 0480 BOOST_MYSQL_RETURN_TYPE(detail::async_connect_v2_t<CompletionToken&&>) 0481 { 0482 return async_connect(params, impl_.shared_diag(), std::forward<CompletionToken>(token)); 0483 } 0484 0485 /** 0486 * \brief Executes a text query or prepared statement. 0487 * \details 0488 * Sends `req` to the server for execution and reads the response into `result`. 0489 * `result` may be either a \ref results or \ref static_results object. 0490 * `req` should may be either a type convertible to \ref string_view containing valid SQL 0491 * or a bound prepared statement, obtained by calling \ref statement::bind. 0492 * If a string, it must be encoded using the connection's character set. 0493 * Any string parameters provided to \ref statement::bind should also be encoded 0494 * using the connection's character set. 0495 * \n 0496 * After this operation completes successfully, `result.has_value() == true`. 0497 * \n 0498 * Metadata in `result` will be populated according to `this->meta_mode()`. 0499 */ 0500 template <BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType> 0501 void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag) 0502 { 0503 impl_.execute(std::forward<ExecutionRequest>(req), result, err, diag); 0504 } 0505 0506 /// \copydoc execute 0507 template <BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_RESULTS_TYPE ResultsType> 0508 void execute(ExecutionRequest&& req, ResultsType& result) 0509 { 0510 error_code err; 0511 diagnostics diag; 0512 execute(std::forward<ExecutionRequest>(req), result, err, diag); 0513 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0514 } 0515 0516 /** 0517 * \copydoc execute 0518 * \par Object lifetimes 0519 * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the caller is 0520 * responsible for managing `req`'s validity following these rules: 0521 * \n 0522 * \li If `req` is `string_view`, the string pointed to by `req` 0523 * must be kept alive by the caller until the operation is initiated. 0524 * \li If `req` is a \ref bound_statement_tuple, and any of the parameters is a reference 0525 * type (like `string_view`), the caller must keep the values pointed by these references alive 0526 * until the operation is initiated. 0527 * \li If `req` is a \ref bound_statement_iterator_range, the caller must keep objects in 0528 * the iterator range passed to \ref statement::bind alive until the operation is initiated. 0529 * 0530 * \par Handler signature 0531 * The handler signature for this operation is `void(boost::mysql::error_code)`. 0532 * 0533 * \par Executor 0534 * Intermediate completion handlers, as well as the final handler, are executed using 0535 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0536 * executor. 0537 * 0538 * If the final handler has an associated immediate executor, and the operation 0539 * completes immediately, the final handler is dispatched to it. 0540 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0541 * and is never be called inline from within this function. 0542 */ 0543 template < 0544 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0545 BOOST_MYSQL_RESULTS_TYPE ResultsType, 0546 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0547 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0548 auto async_execute(ExecutionRequest&& req, ResultsType& result, CompletionToken&& token = {}) 0549 BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t<ExecutionRequest&&, ResultsType, CompletionToken&&>) 0550 { 0551 return async_execute( 0552 std::forward<ExecutionRequest>(req), 0553 result, 0554 impl_.shared_diag(), 0555 std::forward<CompletionToken>(token) 0556 ); 0557 } 0558 0559 /// \copydoc async_execute 0560 template < 0561 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0562 BOOST_MYSQL_RESULTS_TYPE ResultsType, 0563 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0564 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0565 auto async_execute( 0566 ExecutionRequest&& req, 0567 ResultsType& result, 0568 diagnostics& diag, 0569 CompletionToken&& token = {} 0570 ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t<ExecutionRequest&&, ResultsType, CompletionToken&&>) 0571 { 0572 return impl_.async_execute( 0573 std::forward<ExecutionRequest>(req), 0574 result, 0575 diag, 0576 std::forward<CompletionToken>(token) 0577 ); 0578 } 0579 0580 /** 0581 * \brief Starts a SQL execution as a multi-function operation. 0582 * \details 0583 * Writes the execution request and reads the initial server response and the column 0584 * metadata, but not the generated rows or subsequent resultsets, if any. 0585 * `st` may be either an \ref execution_state or \ref static_execution_state object. 0586 * \n 0587 * After this operation completes, `st` will have 0588 * \ref execution_state::meta populated. 0589 * Metadata will be populated according to `this->meta_mode()`. 0590 * \n 0591 * If the operation generated any rows or more than one resultset, these <b>must</b> be read (by using 0592 * \ref read_some_rows and \ref read_resultset_head) before engaging in any further network operation. 0593 * Otherwise, the results are undefined. 0594 * \n 0595 * req may be either a type convertible to \ref string_view containing valid SQL 0596 * or a bound prepared statement, obtained by calling \ref statement::bind. 0597 * If a string, it must be encoded using the connection's character set. 0598 * Any string parameters provided to \ref statement::bind should also be encoded 0599 * using the connection's character set. 0600 * \n 0601 * When using the static interface, this function will detect schema mismatches for the first 0602 * resultset. Further errors may be detected by \ref read_resultset_head and \ref read_some_rows. 0603 * \n 0604 */ 0605 template < 0606 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0607 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> 0608 void start_execution(ExecutionRequest&& req, ExecutionStateType& st, error_code& err, diagnostics& diag) 0609 { 0610 impl_.start_execution(std::forward<ExecutionRequest>(req), st, err, diag); 0611 } 0612 0613 /// \copydoc start_execution 0614 template < 0615 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0616 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> 0617 void start_execution(ExecutionRequest&& req, ExecutionStateType& st) 0618 { 0619 error_code err; 0620 diagnostics diag; 0621 start_execution(std::forward<ExecutionRequest>(req), st, err, diag); 0622 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0623 } 0624 0625 /** 0626 * \copydoc start_execution 0627 * \par Object lifetimes 0628 * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the caller is 0629 * responsible for managing `req`'s validity following these rules: 0630 * \n 0631 * \li If `req` is `string_view`, the string pointed to by `req` 0632 * must be kept alive by the caller until the operation is initiated. 0633 * \li If `req` is a \ref bound_statement_tuple, and any of the parameters is a reference 0634 * type (like `string_view`), the caller must keep the values pointed by these references alive 0635 * until the operation is initiated. 0636 * \li If `req` is a \ref bound_statement_iterator_range, the caller must keep objects in 0637 * the iterator range passed to \ref statement::bind alive until the operation is initiated. 0638 * 0639 * \par Handler signature 0640 * The handler signature for this operation is `void(boost::mysql::error_code)`. 0641 * 0642 * \par Executor 0643 * Intermediate completion handlers, as well as the final handler, are executed using 0644 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0645 * executor. 0646 * 0647 * If the final handler has an associated immediate executor, and the operation 0648 * completes immediately, the final handler is dispatched to it. 0649 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0650 * and is never be called inline from within this function. 0651 */ 0652 template < 0653 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0654 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, 0655 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0656 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0657 auto async_start_execution(ExecutionRequest&& req, ExecutionStateType& st, CompletionToken&& token = {}) 0658 BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< 0659 ExecutionRequest&&, 0660 ExecutionStateType, 0661 CompletionToken&&>) 0662 { 0663 return async_start_execution( 0664 std::forward<ExecutionRequest>(req), 0665 st, 0666 impl_.shared_diag(), 0667 std::forward<CompletionToken>(token) 0668 ); 0669 } 0670 0671 /// \copydoc async_start_execution 0672 template < 0673 BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, 0674 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, 0675 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0676 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0677 auto async_start_execution( 0678 ExecutionRequest&& req, 0679 ExecutionStateType& st, 0680 diagnostics& diag, 0681 CompletionToken&& token = {} 0682 ) 0683 BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< 0684 ExecutionRequest&&, 0685 ExecutionStateType, 0686 CompletionToken&&>) 0687 { 0688 return impl_.async_start_execution( 0689 std::forward<ExecutionRequest>(req), 0690 st, 0691 diag, 0692 std::forward<CompletionToken>(token) 0693 ); 0694 } 0695 0696 /** 0697 * \brief Prepares a statement server-side. 0698 * \details 0699 * `stmt` should be encoded using the connection's character set. 0700 * \n 0701 * The returned statement has `valid() == true`. 0702 */ 0703 statement prepare_statement(string_view stmt, error_code& err, diagnostics& diag) 0704 { 0705 return impl_.run(detail::prepare_statement_algo_params{stmt}, err, diag); 0706 } 0707 0708 /// \copydoc prepare_statement 0709 statement prepare_statement(string_view stmt) 0710 { 0711 error_code err; 0712 diagnostics diag; 0713 statement res = prepare_statement(stmt, err, diag); 0714 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0715 return res; 0716 } 0717 0718 /** 0719 * \copydoc prepare_statement 0720 * \details 0721 * \par Object lifetimes 0722 * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the string 0723 * pointed to by `stmt` must be kept alive by the caller until the operation is 0724 * initiated. 0725 * 0726 * \par Handler signature 0727 * The handler signature for this operation is `void(boost::mysql::error_code, boost::mysql::statement)`. 0728 * 0729 * \par Executor 0730 * Intermediate completion handlers, as well as the final handler, are executed using 0731 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0732 * executor. 0733 * 0734 * If the final handler has an associated immediate executor, and the operation 0735 * completes immediately, the final handler is dispatched to it. 0736 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0737 * and is never be called inline from within this function. 0738 */ 0739 template < 0740 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement)) 0741 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0742 auto async_prepare_statement(string_view stmt, CompletionToken&& token = {}) 0743 BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t<CompletionToken&&>) 0744 { 0745 return async_prepare_statement(stmt, impl_.shared_diag(), std::forward<CompletionToken>(token)); 0746 } 0747 0748 /// \copydoc async_prepare_statement 0749 template < 0750 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement)) 0751 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0752 auto async_prepare_statement(string_view stmt, diagnostics& diag, CompletionToken&& token = {}) 0753 BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t<CompletionToken&&>) 0754 { 0755 return impl_.async_run( 0756 detail::prepare_statement_algo_params{stmt}, 0757 diag, 0758 std::forward<CompletionToken>(token) 0759 ); 0760 } 0761 0762 /** 0763 * \brief Closes a statement, deallocating it from the server. 0764 * \details 0765 * After this operation succeeds, `stmt` must not be used again for execution. 0766 * \n 0767 * \par Preconditions 0768 * `stmt.valid() == true` 0769 */ 0770 void close_statement(const statement& stmt, error_code& err, diagnostics& diag) 0771 { 0772 impl_.run(impl_.make_params_close_statement(stmt), err, diag); 0773 } 0774 0775 /// \copydoc close_statement 0776 void close_statement(const statement& stmt) 0777 { 0778 error_code err; 0779 diagnostics diag; 0780 close_statement(stmt, err, diag); 0781 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0782 } 0783 0784 /** 0785 * \copydoc close_statement 0786 * \details 0787 * \par Object lifetimes 0788 * It is not required to keep `stmt` alive, as copies are made by the implementation as required. 0789 * 0790 * \par Handler signature 0791 * The handler signature for this operation is `void(boost::mysql::error_code)`. 0792 * 0793 * \par Executor 0794 * Intermediate completion handlers, as well as the final handler, are executed using 0795 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0796 * executor. 0797 * 0798 * If the final handler has an associated immediate executor, and the operation 0799 * completes immediately, the final handler is dispatched to it. 0800 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0801 * and is never be called inline from within this function. 0802 */ 0803 template < 0804 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0805 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0806 auto async_close_statement(const statement& stmt, CompletionToken&& token = {}) 0807 BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t<CompletionToken&&>) 0808 { 0809 return async_close_statement(stmt, impl_.shared_diag(), std::forward<CompletionToken>(token)); 0810 } 0811 0812 /// \copydoc async_close_statement 0813 template < 0814 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 0815 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0816 auto async_close_statement(const statement& stmt, diagnostics& diag, CompletionToken&& token = {}) 0817 BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t<CompletionToken&&>) 0818 { 0819 return impl_ 0820 .async_run(impl_.make_params_close_statement(stmt), diag, std::forward<CompletionToken>(token)); 0821 } 0822 0823 /** 0824 * \brief Reads a batch of rows. 0825 * \details 0826 * The number of rows that will be read is unspecified. If the operation represented by `st` 0827 * has still rows to read, at least one will be read. If there are no more rows, or 0828 * `st.should_read_rows() == false`, returns an empty `rows_view`. 0829 * \n 0830 * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer, 0831 * the greater the batch size (up to a maximum). You can set the initial buffer size in the 0832 * constructor. The buffer may be 0833 * grown bigger by other read operations, if required. 0834 * \n 0835 * The returned view points into memory owned by `*this`. It will be valid until 0836 * `*this` performs the next network operation or is destroyed. 0837 */ 0838 rows_view read_some_rows(execution_state& st, error_code& err, diagnostics& diag) 0839 { 0840 return impl_.run(impl_.make_params_read_some_rows(st), err, diag); 0841 } 0842 0843 /// \copydoc read_some_rows(execution_state&,error_code&,diagnostics&) 0844 rows_view read_some_rows(execution_state& st) 0845 { 0846 error_code err; 0847 diagnostics diag; 0848 rows_view res = read_some_rows(st, err, diag); 0849 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0850 return res; 0851 } 0852 0853 /** 0854 * \copydoc read_some_rows(execution_state&,error_code&,diagnostics&) 0855 * \details 0856 * \par Handler signature 0857 * The handler signature for this operation is 0858 * `void(boost::mysql::error_code, boost::mysql::rows_view)`. 0859 * 0860 * \par Executor 0861 * Intermediate completion handlers, as well as the final handler, are executed using 0862 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 0863 * executor. 0864 * 0865 * If the final handler has an associated immediate executor, and the operation 0866 * completes immediately, the final handler is dispatched to it. 0867 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 0868 * and is never be called inline from within this function. 0869 */ 0870 template < 0871 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) 0872 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0873 auto async_read_some_rows(execution_state& st, CompletionToken&& token = {}) 0874 BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t<CompletionToken&&>) 0875 { 0876 return async_read_some_rows(st, impl_.shared_diag(), std::forward<CompletionToken>(token)); 0877 } 0878 0879 /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&) 0880 template < 0881 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) 0882 CompletionToken = with_diagnostics_t<asio::deferred_t>> 0883 auto async_read_some_rows(execution_state& st, diagnostics& diag, CompletionToken&& token = {}) 0884 BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t<CompletionToken&&>) 0885 { 0886 return impl_ 0887 .async_run(impl_.make_params_read_some_rows(st), diag, std::forward<CompletionToken>(token)); 0888 } 0889 0890 #ifdef BOOST_MYSQL_CXX14 0891 0892 /** 0893 * \brief Reads a batch of rows. 0894 * \details 0895 * Reads a batch of rows of unspecified size into the storage given by `output`. 0896 * At most `output.size()` rows will be read. If the operation represented by `st` 0897 * has still rows to read, and `output.size() > 0`, at least one row will be read. 0898 * \n 0899 * Returns the number of read rows. 0900 * \n 0901 * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns 0902 * zero. 0903 * \n 0904 * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer, 0905 * the greater the batch size (up to a maximum). You can set the initial buffer size in the 0906 * constructor. The buffer may be grown bigger by other read operations, if required. 0907 * \n 0908 * Rows read by this function are owning objects, and don't hold any reference to 0909 * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). 0910 * \n 0911 * The type `SpanElementType` must be the underlying row type for one of the types in the 0912 * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`). 0913 * The type must match the resultset that is currently being processed by `st`. For instance, 0914 * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType` 0915 * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued. 0916 * \n 0917 * This function can report schema mismatches. 0918 */ 0919 template <class SpanElementType, class... StaticRow> 0920 std::size_t read_some_rows( 0921 static_execution_state<StaticRow...>& st, 0922 span<SpanElementType> output, 0923 error_code& err, 0924 diagnostics& diag 0925 ) 0926 { 0927 return impl_.run(impl_.make_params_read_some_rows_static(st, output), err, diag); 0928 } 0929 0930 /** 0931 * \brief Reads a batch of rows. 0932 * \details 0933 * Reads a batch of rows of unspecified size into the storage given by `output`. 0934 * At most `output.size()` rows will be read. If the operation represented by `st` 0935 * has still rows to read, and `output.size() > 0`, at least one row will be read. 0936 * \n 0937 * Returns the number of read rows. 0938 * \n 0939 * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns 0940 * zero. 0941 * \n 0942 * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer, 0943 * the greater the batch size (up to a maximum). You can set the initial buffer size in the 0944 * constructor. The buffer may be grown bigger by other read operations, if required. 0945 * \n 0946 * Rows read by this function are owning objects, and don't hold any reference to 0947 * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). 0948 * \n 0949 * The type `SpanElementType` must be the underlying row type for one of the types in the 0950 * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`). 0951 * The type must match the resultset that is currently being processed by `st`. For instance, 0952 * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType` 0953 * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued. 0954 * \n 0955 * This function can report schema mismatches. 0956 */ 0957 template <class SpanElementType, class... StaticRow> 0958 std::size_t read_some_rows(static_execution_state<StaticRow...>& st, span<SpanElementType> output) 0959 { 0960 error_code err; 0961 diagnostics diag; 0962 std::size_t res = read_some_rows(st, output, err, diag); 0963 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 0964 return res; 0965 } 0966 0967 /** 0968 * \brief Reads a batch of rows. 0969 * \details 0970 * Reads a batch of rows of unspecified size into the storage given by `output`. 0971 * At most `output.size()` rows will be read. If the operation represented by `st` 0972 * has still rows to read, and `output.size() > 0`, at least one row will be read. 0973 * \n 0974 * Returns the number of read rows. 0975 * \n 0976 * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns 0977 * zero. 0978 * \n 0979 * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer, 0980 * the greater the batch size (up to a maximum). You can set the initial buffer size in the 0981 * constructor. The buffer may be grown bigger by other read operations, if required. 0982 * \n 0983 * Rows read by this function are owning objects, and don't hold any reference to 0984 * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). 0985 * \n 0986 * The type `SpanElementType` must be the underlying row type for one of the types in the 0987 * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`). 0988 * The type must match the resultset that is currently being processed by `st`. For instance, 0989 * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType` 0990 * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued. 0991 * \n 0992 * This function can report schema mismatches. 0993 * 0994 * \par Handler signature 0995 * The handler signature for this operation is 0996 * `void(boost::mysql::error_code, std::size_t)`. 0997 * 0998 * \par Executor 0999 * Intermediate completion handlers, as well as the final handler, are executed using 1000 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1001 * executor. 1002 * 1003 * If the final handler has an associated immediate executor, and the operation 1004 * completes immediately, the final handler is dispatched to it. 1005 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1006 * and is never be called inline from within this function. 1007 * 1008 * \par Object lifetimes 1009 * The storage that `output` references must be kept alive until the operation completes. 1010 */ 1011 template < 1012 class SpanElementType, 1013 class... StaticRow, 1014 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) 1015 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1016 auto async_read_some_rows( 1017 static_execution_state<StaticRow...>& st, 1018 span<SpanElementType> output, 1019 CompletionToken&& token = {} 1020 ) 1021 { 1022 return async_read_some_rows(st, output, impl_.shared_diag(), std::forward<CompletionToken>(token)); 1023 } 1024 1025 /** 1026 * \brief Reads a batch of rows. 1027 * \details 1028 * Reads a batch of rows of unspecified size into the storage given by `output`. 1029 * At most `output.size()` rows will be read. If the operation represented by `st` 1030 * has still rows to read, and `output.size() > 0`, at least one row will be read. 1031 * \n 1032 * Returns the number of read rows. 1033 * \n 1034 * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns 1035 * zero. 1036 * \n 1037 * The number of rows that will be read depends on the connection's buffer size. The bigger the buffer, 1038 * the greater the batch size (up to a maximum). You can set the initial buffer size in the 1039 * constructor. The buffer may be grown bigger by other read operations, if required. 1040 * \n 1041 * Rows read by this function are owning objects, and don't hold any reference to 1042 * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). 1043 * \n 1044 * The type `SpanElementType` must be the underlying row type for one of the types in the 1045 * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t<StaticRow>...`). 1046 * The type must match the resultset that is currently being processed by `st`. For instance, 1047 * given `static_execution_state<T1, T2>`, when reading rows for the second resultset, `SpanElementType` 1048 * must exactly be `underlying_row_t<T2>`. If this is not the case, a runtime error will be issued. 1049 * \n 1050 * This function can report schema mismatches. 1051 * 1052 * \par Handler signature 1053 * The handler signature for this operation is 1054 * `void(boost::mysql::error_code, std::size_t)`. 1055 * 1056 * \par Executor 1057 * Intermediate completion handlers, as well as the final handler, are executed using 1058 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1059 * executor. 1060 * 1061 * If the final handler has an associated immediate executor, and the operation 1062 * completes immediately, the final handler is dispatched to it. 1063 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1064 * and is never be called inline from within this function. 1065 * 1066 * \par Object lifetimes 1067 * The storage that `output` references must be kept alive until the operation completes. 1068 */ 1069 template < 1070 class SpanElementType, 1071 class... StaticRow, 1072 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) 1073 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1074 auto async_read_some_rows( 1075 static_execution_state<StaticRow...>& st, 1076 span<SpanElementType> output, 1077 diagnostics& diag, 1078 CompletionToken&& token = {} 1079 ) 1080 { 1081 return impl_.async_run( 1082 impl_.make_params_read_some_rows_static(st, output), 1083 diag, 1084 std::forward<CompletionToken>(token) 1085 ); 1086 } 1087 #endif 1088 1089 /** 1090 * \brief Reads metadata for subsequent resultsets in a multi-resultset operation. 1091 * \details 1092 * If `st.should_read_head() == true`, this function will read the next resultset's 1093 * initial response message and metadata, if any. If the resultset indicates a failure 1094 * (e.g. the query associated to this resultset contained an error), this function will fail 1095 * with that error. 1096 * \n 1097 * If `st.should_read_head() == false`, this function is a no-op. 1098 * \n 1099 * `st` may be either an \ref execution_state or \ref static_execution_state object. 1100 * \n 1101 * This function is only relevant when using multi-function operations with statements 1102 * that return more than one resultset. 1103 * \n 1104 * When using the static interface, this function will detect schema mismatches for the resultset 1105 * currently being read. Further errors may be detected by subsequent invocations of this function 1106 * and by \ref read_some_rows. 1107 * \n 1108 */ 1109 template <BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> 1110 void read_resultset_head(ExecutionStateType& st, error_code& err, diagnostics& diag) 1111 { 1112 return impl_.run(impl_.make_params_read_resultset_head(st), err, diag); 1113 } 1114 1115 /// \copydoc read_resultset_head 1116 template <BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> 1117 void read_resultset_head(ExecutionStateType& st) 1118 { 1119 error_code err; 1120 diagnostics diag; 1121 read_resultset_head(st, err, diag); 1122 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1123 } 1124 1125 /** 1126 * \copydoc read_resultset_head 1127 * \par Handler signature 1128 * The handler signature for this operation is 1129 * `void(boost::mysql::error_code)`. 1130 * 1131 * \par Executor 1132 * Intermediate completion handlers, as well as the final handler, are executed using 1133 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1134 * executor. 1135 * 1136 * If the final handler has an associated immediate executor, and the operation 1137 * completes immediately, the final handler is dispatched to it. 1138 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1139 * and is never be called inline from within this function. 1140 */ 1141 template < 1142 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, 1143 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1144 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1145 auto async_read_resultset_head(ExecutionStateType& st, CompletionToken&& token = {}) 1146 BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t<CompletionToken&&>) 1147 { 1148 return async_read_resultset_head(st, impl_.shared_diag(), std::forward<CompletionToken>(token)); 1149 } 1150 1151 /// \copydoc async_read_resultset_head 1152 template < 1153 BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, 1154 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1155 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1156 auto async_read_resultset_head(ExecutionStateType& st, diagnostics& diag, CompletionToken&& token = {}) 1157 BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t<CompletionToken&&>) 1158 { 1159 return impl_ 1160 .async_run(impl_.make_params_read_resultset_head(st), diag, std::forward<CompletionToken>(token)); 1161 } 1162 1163 /** 1164 * \brief Sets the connection's character set, as per SET NAMES. 1165 * \details 1166 * Sets the connection's character set by running a 1167 * <a href="https://dev.mysql.com/doc/refman/8.0/en/set-names.html">`SET NAMES`</a> 1168 * SQL statement, using the passed \ref character_set::name as the charset name to set. 1169 * \n 1170 * This function will also update the value returned by \ref current_character_set, so 1171 * prefer using this function over raw SQL statements. 1172 * \n 1173 * If the server was unable to set the character set to the requested value (e.g. because 1174 * the server does not support the requested charset), this function will fail, 1175 * as opposed to how \ref connect behaves when an unsupported collation is passed. 1176 * This is a limitation of MySQL servers. 1177 * \n 1178 * You need to perform connection establishment for this function to succeed, since it 1179 * involves communicating with the server. 1180 * 1181 * \par Object lifetimes 1182 * `charset` will be copied as required, and does not need to be kept alive. 1183 */ 1184 void set_character_set(const character_set& charset, error_code& err, diagnostics& diag) 1185 { 1186 impl_.run(detail::set_character_set_algo_params{charset}, err, diag); 1187 } 1188 1189 /// \copydoc set_character_set 1190 void set_character_set(const character_set& charset) 1191 { 1192 error_code err; 1193 diagnostics diag; 1194 set_character_set(charset, err, diag); 1195 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1196 } 1197 1198 /** 1199 * \copydoc set_character_set 1200 * \details 1201 * \n 1202 * \par Handler signature 1203 * The handler signature for this operation is `void(boost::mysql::error_code)`. 1204 * 1205 * \par Executor 1206 * Intermediate completion handlers, as well as the final handler, are executed using 1207 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1208 * executor. 1209 * 1210 * If the final handler has an associated immediate executor, and the operation 1211 * completes immediately, the final handler is dispatched to it. 1212 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1213 * and is never be called inline from within this function. 1214 */ 1215 template < 1216 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1217 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1218 auto async_set_character_set(const character_set& charset, CompletionToken&& token = {}) 1219 BOOST_MYSQL_RETURN_TYPE(detail::async_set_character_set_t<CompletionToken&&>) 1220 { 1221 return async_set_character_set(charset, impl_.shared_diag(), std::forward<CompletionToken>(token)); 1222 } 1223 1224 /// \copydoc async_set_character_set 1225 template < 1226 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1227 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1228 auto async_set_character_set( 1229 const character_set& charset, 1230 diagnostics& diag, 1231 CompletionToken&& token = {} 1232 ) BOOST_MYSQL_RETURN_TYPE(detail::async_set_character_set_t<CompletionToken&&>) 1233 { 1234 return impl_.async_run( 1235 detail::set_character_set_algo_params{charset}, 1236 diag, 1237 std::forward<CompletionToken>(token) 1238 ); 1239 } 1240 1241 /** 1242 * \brief Checks whether the server is alive. 1243 * \details 1244 * If the server is alive, this function will complete without error. 1245 * If it's not, it will fail with the relevant network or protocol error. 1246 * \n 1247 * Note that ping requests are treated as any other type of request at the protocol 1248 * level, and won't be prioritized anyhow by the server. If the server is stuck 1249 * in a long-running query, the ping request won't be answered until the query is 1250 * finished. 1251 */ 1252 void ping(error_code& err, diagnostics& diag) { impl_.run(detail::ping_algo_params{}, err, diag); } 1253 1254 /// \copydoc ping 1255 void ping() 1256 { 1257 error_code err; 1258 diagnostics diag; 1259 ping(err, diag); 1260 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1261 } 1262 1263 /** 1264 * \copydoc ping 1265 * \details 1266 * \n 1267 * \par Handler signature 1268 * The handler signature for this operation is `void(boost::mysql::error_code)`. 1269 * 1270 * \par Executor 1271 * Intermediate completion handlers, as well as the final handler, are executed using 1272 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1273 * executor. 1274 * 1275 * If the final handler has an associated immediate executor, and the operation 1276 * completes immediately, the final handler is dispatched to it. 1277 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1278 * and is never be called inline from within this function. 1279 */ 1280 template < 1281 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1282 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1283 auto async_ping(CompletionToken&& token = {}) 1284 BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t<CompletionToken&&>) 1285 { 1286 return async_ping(impl_.shared_diag(), std::forward<CompletionToken>(token)); 1287 } 1288 1289 /// \copydoc async_ping 1290 template < 1291 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1292 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1293 auto async_ping(diagnostics& diag, CompletionToken&& token = {}) 1294 BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t<CompletionToken&&>) 1295 { 1296 return impl_.async_run(detail::ping_algo_params{}, diag, std::forward<CompletionToken>(token)); 1297 } 1298 1299 /** 1300 * \brief Resets server-side session state, like variables and prepared statements. 1301 * \details 1302 * Resets all server-side state for the current session: 1303 * \n 1304 * \li Rolls back any active transactions and resets autocommit mode. 1305 * \li Releases all table locks. 1306 * \li Drops all temporary tables. 1307 * \li Resets all session system variables to their default values (including the ones set by `SET 1308 * NAMES`) and clears all user-defined variables. 1309 * \li Closes all prepared statements. 1310 * \n 1311 * A full reference on the affected session state can be found 1312 * <a href="https://dev.mysql.com/doc/c-api/8.0/en/mysql-reset-connection.html">here</a>. 1313 * \n 1314 * \n 1315 * This function will not reset the current physical connection and won't cause re-authentication. 1316 * It is faster than closing and re-opening a connection. 1317 * \n 1318 * The connection must be connected and authenticated before calling this function. 1319 * This function involves communication with the server, and thus may fail. 1320 * 1321 * \par Warning on character sets 1322 * This function will restore the connection's character set and collation **to the server's default**, 1323 * and not to the one specified during connection establishment. Some servers have `latin1` as their 1324 * default character set, which is not usually what you want. Since there is no way to know this 1325 * character set, \ref current_character_set will return `nullptr` after the operation succeeds. 1326 * We recommend always using \ref set_character_set or \ref async_set_character_set after calling this 1327 * function. 1328 * \n 1329 * You can find the character set that your server will use after the reset by running: 1330 * \code 1331 * "SELECT @@global.character_set_client, @@global.character_set_results;" 1332 * \endcode 1333 */ 1334 void reset_connection(error_code& err, diagnostics& diag) 1335 { 1336 impl_.run(detail::reset_connection_algo_params{}, err, diag); 1337 } 1338 1339 /// \copydoc reset_connection 1340 void reset_connection() 1341 { 1342 error_code err; 1343 diagnostics diag; 1344 reset_connection(err, diag); 1345 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1346 } 1347 1348 /** 1349 * \copydoc reset_connection 1350 * \details 1351 * \n 1352 * \par Handler signature 1353 * The handler signature for this operation is `void(boost::mysql::error_code)`. 1354 * 1355 * \par Executor 1356 * Intermediate completion handlers, as well as the final handler, are executed using 1357 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1358 * executor. 1359 * 1360 * If the final handler has an associated immediate executor, and the operation 1361 * completes immediately, the final handler is dispatched to it. 1362 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1363 * and is never be called inline from within this function. 1364 */ 1365 template < 1366 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1367 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1368 auto async_reset_connection(CompletionToken&& token = {}) 1369 BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t<CompletionToken&&>) 1370 { 1371 return async_reset_connection(impl_.shared_diag(), std::forward<CompletionToken>(token)); 1372 } 1373 1374 /// \copydoc async_reset_connection 1375 template < 1376 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) 1377 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1378 auto async_reset_connection(diagnostics& diag, CompletionToken&& token = {}) 1379 BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t<CompletionToken&&>) 1380 { 1381 return impl_ 1382 .async_run(detail::reset_connection_algo_params{}, diag, std::forward<CompletionToken>(token)); 1383 } 1384 1385 /** 1386 * \brief Cleanly closes the connection to the server. 1387 * \details 1388 * This function does the following: 1389 * \n 1390 * \li Sends a quit request. This is required by the MySQL protocol, to inform 1391 * the server that we're closing the connection gracefully. 1392 * \li If the connection is using TLS (`this->uses_ssl() == true`), performs 1393 * the TLS shutdown. 1394 * \li Closes the transport-level connection (the TCP or UNIX socket). 1395 * \n 1396 * Since this function involves writing a message to the server, it can fail. 1397 * Only use this function if you know that the connection is healthy and you want 1398 * to cleanly close it. 1399 * \n 1400 * If you don't call this function, the destructor or successive connects will 1401 * perform a transport-layer close. This doesn't cause any resource leaks, but may 1402 * cause warnings to be written to the server logs. 1403 */ 1404 void close(error_code& err, diagnostics& diag) 1405 { 1406 impl_.run(detail::close_connection_algo_params{}, err, diag); 1407 } 1408 1409 /// \copydoc close 1410 void close() 1411 { 1412 error_code err; 1413 diagnostics diag; 1414 close(err, diag); 1415 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1416 } 1417 1418 /** 1419 * \copydoc close 1420 * \details 1421 * \par Handler signature 1422 * The handler signature for this operation is `void(boost::mysql::error_code)`. 1423 * 1424 * \par Executor 1425 * Intermediate completion handlers, as well as the final handler, are executed using 1426 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1427 * executor. 1428 * 1429 * If the final handler has an associated immediate executor, and the operation 1430 * completes immediately, the final handler is dispatched to it. 1431 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1432 * and is never be called inline from within this function. 1433 */ 1434 template < 1435 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 1436 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1437 auto async_close(CompletionToken&& token = {}) 1438 BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t<CompletionToken&&>) 1439 { 1440 return async_close(impl_.shared_diag(), std::forward<CompletionToken>(token)); 1441 } 1442 1443 /// \copydoc async_close 1444 template < 1445 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 1446 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1447 auto async_close(diagnostics& diag, CompletionToken&& token = {}) 1448 BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t<CompletionToken&&>) 1449 { 1450 return this->impl_ 1451 .async_run(detail::close_connection_algo_params{}, diag, std::forward<CompletionToken>(token)); 1452 } 1453 1454 /** 1455 * \brief Runs a set of pipelined requests. 1456 * \details 1457 * Runs the pipeline described by `req` and stores its response in `res`. 1458 * After the operation completes, `res` will have as many elements as stages 1459 * were in `req`, even if the operation fails. 1460 * \n 1461 * Request stages are seen by the server as a series of unrelated requests. 1462 * As a consequence, all stages are always run, even if previous stages fail. 1463 * \n 1464 * If all stages succeed, the operation completes successfully. Thus, there is no need to check 1465 * the per-stage error code in `res` if this operation completed successfully. 1466 * \n 1467 * If any stage fails with a non-fatal error (as per \ref is_fatal_error), the result of the operation 1468 * is the first encountered error. You can check which stages succeeded and which ones didn't by 1469 * inspecting each stage in `res`. 1470 * \n 1471 * If any stage fails with a fatal error, the result of the operation is the fatal error. 1472 * Successive stages will be marked as failed with the fatal error. The server may or may 1473 * not have processed such stages. 1474 */ 1475 void run_pipeline( 1476 const pipeline_request& req, 1477 std::vector<stage_response>& res, 1478 error_code& err, 1479 diagnostics& diag 1480 ) 1481 { 1482 impl_.run(impl_.make_params_pipeline(req, res), err, diag); 1483 } 1484 1485 /// \copydoc run_pipeline 1486 void run_pipeline(const pipeline_request& req, std::vector<stage_response>& res) 1487 { 1488 error_code err; 1489 diagnostics diag; 1490 run_pipeline(req, res, err, diag); 1491 detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); 1492 } 1493 1494 /** 1495 * \copydoc run_pipeline 1496 * \details 1497 * \par Handler signature 1498 * The handler signature for this operation is `void(boost::mysql::error_code)`. 1499 * 1500 * \par Executor 1501 * Intermediate completion handlers, as well as the final handler, are executed using 1502 * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated 1503 * executor. 1504 * 1505 * If the final handler has an associated immediate executor, and the operation 1506 * completes immediately, the final handler is dispatched to it. 1507 * Otherwise, the final handler is called as if it was submitted using `asio::post`, 1508 * and is never be called inline from within this function. 1509 * 1510 * \par Object lifetimes 1511 * The request and response objects must be kept alive and should not be modified 1512 * until the operation completes. 1513 */ 1514 template < 1515 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 1516 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1517 auto async_run_pipeline( 1518 const pipeline_request& req, 1519 std::vector<stage_response>& res, 1520 CompletionToken&& token = {} 1521 ) BOOST_MYSQL_RETURN_TYPE(detail::async_run_pipeline_t<CompletionToken&&>) 1522 { 1523 return async_run_pipeline(req, res, impl_.shared_diag(), std::forward<CompletionToken>(token)); 1524 } 1525 1526 /// \copydoc async_run_pipeline 1527 template < 1528 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) 1529 CompletionToken = with_diagnostics_t<asio::deferred_t>> 1530 auto async_run_pipeline( 1531 const pipeline_request& req, 1532 std::vector<stage_response>& res, 1533 diagnostics& diag, 1534 CompletionToken&& token = {} 1535 ) BOOST_MYSQL_RETURN_TYPE(detail::async_run_pipeline_t<CompletionToken&&>) 1536 { 1537 return this->impl_ 1538 .async_run(impl_.make_params_pipeline(req, res), diag, std::forward<CompletionToken>(token)); 1539 } 1540 }; 1541 1542 } // namespace mysql 1543 } // namespace boost 1544 1545 #ifdef BOOST_MYSQL_HEADER_ONLY 1546 #include <boost/mysql/impl/any_connection.ipp> 1547 #endif 1548 1549 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |