diff --git a/include/boost/mysql.hpp b/include/boost/mysql.hpp index d6acf4805..eafaa507e 100644 --- a/include/boost/mysql.hpp +++ b/include/boost/mysql.hpp @@ -8,7 +8,6 @@ #ifndef BOOST_MYSQL_HPP #define BOOST_MYSQL_HPP -#include #include #include #include diff --git a/include/boost/mysql/any_connection.hpp b/include/boost/mysql/any_connection.hpp deleted file mode 100644 index 49f77ce07..000000000 --- a/include/boost/mysql/any_connection.hpp +++ /dev/null @@ -1,920 +0,0 @@ -// -// Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_MYSQL_ANY_CONNECTION_HPP -#define BOOST_MYSQL_ANY_CONNECTION_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -/// The Boost libraries namespace. -namespace boost { -/// Boost.MySQL library namespace. -namespace mysql { - -// Forward declarations -template -class static_execution_state; - -// TODO: move this somewhere -struct tcp_address -{ - std::string hostname; - std::string port; -}; - -struct unix_address -{ - std::string path; -}; - -struct named_pipe_address -{ - std::string pipe_name; -}; - -using server_address_type = boost::variant2::variant; - -struct connect_params -{ - server_address_type server_address; - std::string username; - std::string password; - std::string database; - std::uint16_t connection_collation; // TODO: do we want to keep this? - ssl_mode ssl; - bool multi_queries; - boost::asio::ssl::context* ssl_context; - buffer_params buffer_config; - // TODO: timeouts -}; - -class any_connection -{ - detail::channel_ptr channel_; - - diagnostics& shared_diag() noexcept { return channel_.shared_diag(); } - -#ifndef BOOST_MYSQL_DOXYGEN - friend struct detail::access; -#endif - -public: - any_connection(boost::asio::any_io_executor ex); - - /** - * \brief Move constructor. - */ - any_connection(any_connection&& other) = default; - - /** - * \brief Move assignment. - */ - any_connection& operator=(any_connection&& rhs) = default; - -#ifndef BOOST_MYSQL_DOXYGEN - any_connection(const any_connection&) = delete; - any_connection& operator=(const any_connection&) = delete; -#endif - - /// The executor type associated to this object. - using executor_type = boost::asio::any_io_executor; - - /// Retrieves the executor associated to this object. - executor_type get_executor(); - - // TODO: do we need this? - // bool uses_ssl() const noexcept { return channel_.stream().ssl_active(); } - - // TODO: how do we do this? - // metadata_mode meta_mode() const noexcept { return channel_.meta_mode(); } - // void set_meta_mode(metadata_mode v) noexcept { channel_.set_meta_mode(v); } - - void connect(const connect_params& params, error_code& ec, diagnostics& diag); - - /// \copydoc connect - void connect(const connect_params& params) - { - error_code err; - diagnostics diag; - connect(params, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect( - const connect_params& params, // TODO: how do we manage ownership here? - CompletionToken&& token - ) - { - return async_connect(params, this->shared_diag(), std::forward(token)); - } - - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_connect(const connect_params& params, diagnostics& diag, CompletionToken&& token); - - /** - * \brief Executes a text query or prepared statement. - * \details - * Sends `req` to the server for execution and reads the response into `result`. - * `result` may be either a \ref results or \ref static_results object. - * `req` should may be either a type convertible to \ref string_view containing valid SQL - * or a bound prepared statement, obtained by calling \ref statement::bind. - * If a string, it must be encoded using the connection's character set. - * Any string parameters provided to \ref statement::bind should also be encoded - * using the connection's character set. - * \n - * After this operation completes successfully, `result.has_value() == true`. - * \n - * Metadata in `result` will be populated according to `this->meta_mode()`. - */ - template - void execute(const ExecutionRequest& req, ResultsType& result, error_code& err, diagnostics& diag) - { - detail::execute_interface(channel_.get(), req, result, err, diag); - } - - /// \copydoc execute - template - void execute(const ExecutionRequest& req, ResultsType& result) - { - error_code err; - diagnostics diag; - execute(req, result, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc execute - * \par Object lifetimes - * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the caller is - * responsible for managing `req`'s validity following these rules: - * \n - * \li If `req` is `string_view`, the string pointed to by `req` - * must be kept alive by the caller until the operation is initiated. - * \li If `req` is a \ref bound_statement_tuple, and any of the parameters is a reference - * type (like `string_view`), the caller must keep the values pointed by these references alive - * until the operation is initiated. - * \li If `req` is a \ref bound_statement_iterator_range, the caller must keep objects in - * the iterator range passed to \ref statement::bind alive until the operation is initiated. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_RESULTS_TYPE ResultsType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_execute( - ExecutionRequest&& req, - ResultsType& result, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_execute( - std::forward(req), - result, - shared_diag(), - std::forward(token) - ); - } - - /// \copydoc async_execute - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_RESULTS_TYPE ResultsType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_execute( - ExecutionRequest&& req, - ResultsType& result, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return detail::async_execute_interface( - channel_.get(), - std::forward(req), - result, - diag, - std::forward(token) - ); - } - - /** - * \brief Starts a SQL execution as a multi-function operation. - * \details - * Writes the execution request and reads the initial server response and the column - * metadata, but not the generated rows or subsequent resultsets, if any. - * `st` may be either an \ref execution_state or \ref static_execution_state object. - * \n - * After this operation completes, `st` will have - * \ref execution_state::meta populated. - * Metadata will be populated according to `this->meta_mode()`. - * \n - * If the operation generated any rows or more than one resultset, these must be read (by using - * \ref read_some_rows and \ref read_resultset_head) before engaging in any further network operation. - * Otherwise, the results are undefined. - * \n - * req may be either a type convertible to \ref string_view containing valid SQL - * or a bound prepared statement, obtained by calling \ref statement::bind. - * If a string, it must be encoded using the connection's character set. - * Any string parameters provided to \ref statement::bind should also be encoded - * using the connection's character set. - * \n - * When using the static interface, this function will detect schema mismatches for the first - * resultset. Further errors may be detected by \ref read_resultset_head and \ref read_some_rows. - */ - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution( - const ExecutionRequest& req, - ExecutionStateType& st, - error_code& err, - diagnostics& diag - ) - { - detail::start_execution_interface(channel_.get(), req, st, err, diag); - } - - /// \copydoc start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution(const ExecutionRequest& req, ExecutionStateType& st) - { - error_code err; - diagnostics diag; - start_execution(req, st, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc start_execution - * \par Object lifetimes - * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the caller is - * responsible for managing `req`'s validity following these rules: - * \n - * \li If `req` is `string_view`, the string pointed to by `req` - * must be kept alive by the caller until the operation is initiated. - * \li If `req` is a \ref bound_statement_tuple, and any of the parameters is a reference - * type (like `string_view`), the caller must keep the values pointed by these references alive - * until the operation is initiated. - * \li If `req` is a \ref bound_statement_iterator_range, the caller must keep objects in - * the iterator range passed to \ref statement::bind alive until the operation is initiated. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_start_execution( - std::forward(req), - st, - shared_diag(), - std::forward(token) - ); - } - - /// \copydoc async_start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return detail::async_start_execution_interface( - channel_.get(), - std::forward(req), - st, - diag, - std::forward(token) - ); - } - - /** - * \brief Prepares a statement server-side. - * \details - * `stmt` should be encoded using the connection's character set. - * \n - * The returned statement has `valid() == true`. - */ - statement prepare_statement(string_view stmt, error_code& err, diagnostics& diag) - { - return detail::prepare_statement_interface(channel_.get(), stmt, err, diag); - } - - /// \copydoc prepare_statement - statement prepare_statement(string_view stmt) - { - error_code err; - diagnostics diag; - statement res = prepare_statement(stmt, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - return res; - } - - /** - * \copydoc prepare_statement - * \details - * \par Object lifetimes - * If `CompletionToken` is a deferred completion token (e.g. `use_awaitable`), the string - * pointed to by `stmt` must be kept alive by the caller until the operation is - * initiated. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code, boost::mysql::statement)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement)) - async_prepare_statement( - string_view stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_prepare_statement(stmt, shared_diag(), std::forward(token)); - } - - /// \copydoc async_prepare_statement - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, statement)) - async_prepare_statement( - string_view stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return detail::async_prepare_statement_interface( - channel_.get(), - stmt, - diag, - std::forward(token) - ); - } - - /** - * \brief Closes a statement, deallocating it from the server. - * \details - * After this operation succeeds, `stmt` must not be used again for execution. - * \n - * \par Preconditions - * `stmt.valid() == true` - */ - void close_statement(const statement& stmt, error_code& err, diagnostics& diag) - { - detail::close_statement_interface(channel_.get(), stmt, err, diag); - } - - /// \copydoc close_statement - void close_statement(const statement& stmt) - { - error_code err; - diagnostics diag; - close_statement(stmt, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc close_statement - * \details - * \par Object lifetimes - * It is not required to keep `stmt` alive, as copies are made by the implementation as required. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close_statement( - const statement& stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_close_statement(stmt, shared_diag(), std::forward(token)); - } - - /// \copydoc async_close_statement - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close_statement( - const statement& stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return detail::async_close_statement_interface( - channel_.get(), - stmt, - diag, - std::forward(token) - ); - } - - /** - * \brief Reads a batch of rows. - * \details - * The number of rows that will be read is unspecified. If the operation represented by `st` - * has still rows to read, at least one will be read. If there are no more rows, or - * `st.should_read_rows() == false`, returns an empty `rows_view`. - * \n - * The number of rows that will be read depends on the input buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s - * constructor, using \ref buffer_params::initial_read_size. The buffer may be - * grown bigger by other read operations, if required. - * \n - * The returned view points into memory owned by `*this`. It will be valid until - * `*this` performs the next network operation or is destroyed. - */ - rows_view read_some_rows(execution_state& st, error_code& err, diagnostics& diag) - { - return detail::read_some_rows_dynamic_interface(channel_.get(), st, err, diag); - } - - /// \copydoc read_some_rows(execution_state&,error_code&,diagnostics&) - rows_view read_some_rows(execution_state& st) - { - error_code err; - diagnostics diag; - rows_view res = read_some_rows(st, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - return res; - } - - /** - * \copydoc read_some_rows(execution_state&,error_code&,diagnostics&) - * \details - * \par Handler signature - * The handler signature for this operation is - * `void(boost::mysql::error_code, boost::mysql::rows_view)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_some_rows( - execution_state& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_read_some_rows(st, shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&) - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view)) - async_read_some_rows( - execution_state& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return detail::async_read_some_rows_dynamic_interface( - channel_.get(), - st, - diag, - std::forward(token) - ); - } - -#ifdef BOOST_MYSQL_CXX14 - - /** - * \brief Reads a batch of rows. - * \details - * Reads a batch of rows of unspecified size into the storage given by `output`. - * At most `output.size()` rows will be read. If the operation represented by `st` - * has still rows to read, and `output.size() > 0`, at least one row will be read. - * \n - * Returns the number of read rows. - * \n - * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns - * zero. - * \n - * The number of rows that will be read depends on the input buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s - * constructor, using \ref buffer_params::initial_read_size. The buffer may be - * grown bigger by other read operations, if required. - * \n - * Rows read by this function are owning objects, and don't hold any reference to - * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). - * \n - * `SpanStaticRow` must exactly be one of the types in the `StaticRow` parameter pack. - * The type must match the resultset that is currently being processed by `st`. For instance, - * given `static_execution_state`, when reading rows for the second resultset, `SpanStaticRow` - * must exactly be `T2`. If this is not the case, a runtime error will be issued. - * \n - * This function can report schema mismatches. - */ - template - std::size_t read_some_rows( - static_execution_state& st, - span output, - error_code& err, - diagnostics& diag - ) - { - return detail::read_some_rows_static_interface(channel_.get(), st, output, err, diag); - } - - /** - * \brief Reads a batch of rows. - * \details - * Reads a batch of rows of unspecified size into the storage given by `output`. - * At most `output.size()` rows will be read. If the operation represented by `st` - * has still rows to read, and `output.size() > 0`, at least one row will be read. - * \n - * Returns the number of read rows. - * \n - * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns - * zero. - * \n - * The number of rows that will be read depends on the input buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s - * constructor, using \ref buffer_params::initial_read_size. The buffer may be - * grown bigger by other read operations, if required. - * \n - * Rows read by this function are owning objects, and don't hold any reference to - * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). - * \n - * `SpanStaticRow` must exactly be one of the types in the `StaticRow` parameter pack. - * The type must match the resultset that is currently being processed by `st`. For instance, - * given `static_execution_state`, when reading rows for the second resultset, `SpanStaticRow` - * must exactly be `T2`. If this is not the case, a runtime error will be issued. - * \n - * This function can report schema mismatches. - */ - template - std::size_t read_some_rows(static_execution_state& st, span output) - { - error_code err; - diagnostics diag; - std::size_t res = read_some_rows(st, output, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - return res; - } - - /** - * \brief Reads a batch of rows. - * \details - * Reads a batch of rows of unspecified size into the storage given by `output`. - * At most `output.size()` rows will be read. If the operation represented by `st` - * has still rows to read, and `output.size() > 0`, at least one row will be read. - * \n - * Returns the number of read rows. - * \n - * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns - * zero. - * \n - * The number of rows that will be read depends on the input buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s - * constructor, using \ref buffer_params::initial_read_size. The buffer may be - * grown bigger by other read operations, if required. - * \n - * Rows read by this function are owning objects, and don't hold any reference to - * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). - * \n - * `SpanStaticRow` must exactly be one of the types in the `StaticRow` parameter pack. - * The type must match the resultset that is currently being processed by `st`. For instance, - * given `static_execution_state`, when reading rows for the second resultset, `SpanStaticRow` - * must exactly be `T2`. If this is not the case, a runtime error will be issued. - * \n - * This function can report schema mismatches. - * - * \par Handler signature - * The handler signature for this operation is - * `void(boost::mysql::error_code, std::size_t)`. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanStaticRow, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t)) - async_read_some_rows( - static_execution_state& st, - span output, - CompletionToken&& token - ) - { - return async_read_some_rows(st, output, shared_diag(), std::forward(token)); - } - - /** - * \brief Reads a batch of rows. - * \details - * Reads a batch of rows of unspecified size into the storage given by `output`. - * At most `output.size()` rows will be read. If the operation represented by `st` - * has still rows to read, and `output.size() > 0`, at least one row will be read. - * \n - * Returns the number of read rows. - * \n - * If there are no more rows, or `st.should_read_rows() == false`, this function is a no-op and returns - * zero. - * \n - * The number of rows that will be read depends on the input buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in `connection`'s - * constructor, using \ref buffer_params::initial_read_size. The buffer may be - * grown bigger by other read operations, if required. - * \n - * Rows read by this function are owning objects, and don't hold any reference to - * the connection's internal buffers (contrary what happens with the dynamic interface's counterpart). - * \n - * `SpanStaticRow` must exactly be one of the types in the `StaticRow` parameter pack. - * The type must match the resultset that is currently being processed by `st`. For instance, - * given `static_execution_state`, when reading rows for the second resultset, `SpanStaticRow` - * must exactly be `T2`. If this is not the case, a runtime error will be issued. - * \n - * This function can report schema mismatches. - * - * \par Handler signature - * The handler signature for this operation is - * `void(boost::mysql::error_code, std::size_t)`. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanStaticRow, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, std::size_t)) - async_read_some_rows( - static_execution_state& st, - span output, - diagnostics& diag, - CompletionToken&& token - ) - { - return detail::async_read_some_rows_static_interface( - channel_.get(), - st, - output, - diag, - std::forward(token) - ); - } -#endif - - /** - * \brief Reads metadata for subsequent resultsets in a multi-resultset operation. - * \details - * If `st.should_read_head() == true`, this function will read the next resultset's - * initial response message and metadata, if any. If the resultset indicates a failure - * (e.g. the query associated to this resultset contained an error), this function will fail - * with that error. - * \n - * If `st.should_read_head() == false`, this function is a no-op. - * \n - * `st` may be either an \ref execution_state or \ref static_execution_state object. - * \n - * This function is only relevant when using multi-function operations with statements - * that return more than one resultset. - * \n - * When using the static interface, this function will detect schema mismatches for the resultset - * currently being read. Further errors may be detected by subsequent invocations of this function - * and by \ref read_some_rows. - */ - template - void read_resultset_head(ExecutionStateType& st, error_code& err, diagnostics& diag) - { - return detail::read_resultset_head_interface(channel_.get(), st, err, diag); - } - - /// \copydoc read_resultset_head - template - void read_resultset_head(ExecutionStateType& st) - { - error_code err; - diagnostics diag; - read_resultset_head(st, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc read_resultset_head - * \par Handler signature - * The handler signature for this operation is - * `void(boost::mysql::error_code)`. - */ - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_read_resultset_head(ExecutionStateType& st, CompletionToken&& token) - { - return async_read_resultset_head(st, shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_resultset_head - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_read_resultset_head(ExecutionStateType& st, diagnostics& diag, CompletionToken&& token) - { - return detail::async_read_resultset_head_interface( - channel_.get(), - st, - diag, - std::forward(token) - ); - } - - /** - * \brief Checks whether the server is alive. - * \details - * If the server is alive, this function will complete without error. - * If it's not, it will fail with the relevant network or protocol error. - * \n - * Note that ping requests are treated as any other type of request at the protocol - * level, and won't be prioritized anyhow by the server. If the server is stuck - * in a long-running query, the ping request won't be answered until the query is - * finished. - */ - void ping(error_code& err, diagnostics& diag) { detail::ping_interface(channel_.get(), err, diag); } - - /// \copydoc ping - void ping() - { - error_code err; - diagnostics diag; - ping(err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc ping - * \details - * \n - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_ping(CompletionToken&& token) - { - return async_ping(shared_diag(), std::forward(token)); - } - - /// \copydoc async_ping - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_ping(diagnostics& diag, CompletionToken&& token) - { - return detail::async_ping_interface(channel_.get(), diag, std::forward(token)); - } - - /** - * \brief Resets server-side session state, like variables and prepared statements. - * \details - * Resets all server-side state for the current session: - * \n - * \li Rolls back any active transactions and resets autocommit mode. - * \li Releases all table locks. - * \li Drops all temporary tables. - * \li Resets all session system variables to their default values (including the ones set by `SET - * NAMES`) and clears all user-defined variables. \li Closes all prepared statements. - * \n - * A full reference on the affected session state can be found - * here. - * \n - * This function will not reset the current physical connection and won't cause re-authentication. - * It is faster than closing and re-opening a connection. - * \n - * The connection must be connected and authenticated before calling this function. - * This function involves communication with the server, and thus may fail. - */ - void reset_connection(error_code& err, diagnostics& diag) - { - detail::reset_connection_interface(channel_.get(), err, diag); - } - - /// \copydoc reset_connection - void reset_connection() - { - error_code err; - diagnostics diag; - reset_connection(err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc reset_connection - * \details - * \n - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_reset_connection(CompletionToken&& token) - { - return async_reset_connection(shared_diag(), std::forward(token)); - } - - /// \copydoc async_reset_connection - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_reset_connection(diagnostics& diag, CompletionToken&& token) - { - return detail::async_reset_connection_interface( - channel_.get(), - diag, - std::forward(token) - ); - } - - /** - * \brief Closes the connection to the server. - * \details - * This function is only available if `Stream` satisfies the `SocketStream` concept. - * \n - * Sends a quit request, performs the TLS shutdown (if required) - * and closes the underlying stream. Prefer this function to \ref connection::quit. - */ - void close(error_code& err, diagnostics& diag); - - /// \copydoc close - void close() - { - error_code err; - diagnostics diag; - close(err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc close - * \details - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - */ - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close(CompletionToken&& token) - { - return async_close(shared_diag(), std::forward(token)); - } - - /// \copydoc async_close - template - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code)) - async_close(diagnostics& diag, CompletionToken&& token); -}; - -} // namespace mysql -} // namespace boost - -#endif diff --git a/test/unit/Jamfile b/test/unit/Jamfile index 7cdf156bc..1932c32b7 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -33,11 +33,20 @@ run test/protocol/deserialize_binary_field.cpp test/protocol/protocol.cpp - test/channel/read_buffer.cpp - test/channel/message_parser.cpp - test/channel/message_reader.cpp - test/channel/message_writer.cpp - test/channel/write_message.cpp + test/sansio/read_buffer.cpp + test/sansio/message_writer.cpp + test/sansio/message_reader.cpp + test/sansio/algo_runner.cpp + + test/sansio/read_resultset_head.cpp + test/sansio/start_execution.cpp + test/sansio/read_some_rows.cpp + test/sansio/read_some_rows_dynamic.cpp + test/sansio/execute.cpp + test/sansio/close_statement.cpp + test/sansio/ping.cpp + test/sansio/reset_connection.cpp + test/network_algorithms/run_algo_impl.cpp test/execution_processor/execution_processor.cpp test/execution_processor/execution_state_impl.cpp @@ -45,17 +54,6 @@ run test/execution_processor/results_impl.cpp test/execution_processor/static_results_impl.cpp - test/network_algorithms/read_resultset_head.cpp - test/network_algorithms/start_execution.cpp - test/network_algorithms/read_some_rows.cpp - test/network_algorithms/read_some_rows_dynamic.cpp - test/network_algorithms/execute.cpp - test/network_algorithms/close_statement.cpp - test/network_algorithms/ping.cpp - test/network_algorithms/reset_connection.cpp - test/network_algorithms/read_some_rows_static.cpp - - test/detail/any_stream_impl.cpp test/detail/datetime.cpp test/detail/row_impl.cpp test/detail/rows_iterator.cpp @@ -68,9 +66,12 @@ run test/detail/typing/row_traits.cpp test/detail/typing/get_type_index.cpp - test/misc.cpp - test/multifn.cpp - test/default_completion_tokens.cpp + test/spotchecks/connection_use_after_move.cpp + test/spotchecks/default_completion_tokens.cpp + test/spotchecks/read_some_rows_static.cpp + test/spotchecks/multifn.cpp + test/spotchecks/misc.cpp + test/execution_state.cpp test/static_execution_state.cpp test/results.cpp diff --git a/test/unit/include/test_unit/create_channel.hpp b/test/unit/include/test_unit/create_channel.hpp deleted file mode 100644 index 9ddcb1c78..000000000 --- a/test/unit/include/test_unit/create_channel.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_CREATE_CHANNEL_HPP -#define BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_CREATE_CHANNEL_HPP - -#include - -#include - -#include -#include - -#include "test_unit/test_stream.hpp" - -namespace boost { -namespace mysql { -namespace test { - -inline detail::channel create_channel(std::size_t buffer_size = 1024) -{ - return detail::channel(buffer_size, std::unique_ptr(new test_any_stream)); -} - -inline test_stream& get_stream(detail::channel& chan) noexcept -{ - return detail::cast(chan.stream()); -} - -} // namespace test -} // namespace mysql -} // namespace boost - -#endif