diff --git a/.clangd b/.clangd index 328db6981..d90aed0e7 100644 --- a/.clangd +++ b/.clangd @@ -1,3 +1,2 @@ -Diagnostics: - ClangTidy: - Remove: bugprone-unused-return-value \ No newline at end of file +Style: + AngledHeaders: ["boost/.*"] \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c092cb19..c137dc183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,33 @@ cmake_minimum_required(VERSION 3.8...3.22) # Project -project(boost_mysql VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) +project(mycosql LANGUAGES CXX) # Library -add_library(boost_mysql INTERFACE) -add_library(Boost::mysql ALIAS boost_mysql) +add_library(boost_mycosql + src/character_set.cpp + src/column_type.cpp + src/connection.cpp + src/date.cpp + src/datetime.cpp + src/error_categories.cpp + src/escape_string.cpp + src/execution_state_impl.cpp + src/field.cpp + src/field_kind.cpp + src/field_view.cpp + src/format_sql.cpp + src/is_fatal_error.cpp + src/meta_check_context.cpp + src/pipeline.cpp + src/results_impl.cpp + src/resultset.cpp + src/row_impl.cpp + src/server_error_to_string.cpp + src/static_execution_state_impl.cpp + src/static_results_impl.cpp +) +add_library(Boost::mycosql ALIAS boost_mycosql) # Dependencies. If non-Boost dependencies are not found, we just bail out find_package(Threads) @@ -29,9 +51,10 @@ endif() # This is generated by boostdep. # Note that Boost::pfr is not listed because it's a peer dependency target_link_libraries( - boost_mysql - INTERFACE - Boost::asio + boost_mycosql + PUBLIC + Boost::corosio + Boost::corosio_openssl Boost::assert Boost::charconv Boost::compat @@ -52,45 +75,50 @@ target_link_libraries( ) # Includes & features -target_include_directories(boost_mysql INTERFACE include) -target_compile_features(boost_mysql INTERFACE cxx_std_11) +target_include_directories(boost_mycosql PUBLIC include) +target_include_directories(boost_mycosql PRIVATE src) +target_compile_features(boost_mycosql PUBLIC cxx_std_20) -# Don't run integration testing unless explicitly requested, since these require a running MySQL server -option(BOOST_MYSQL_INTEGRATION_TESTS OFF "Whether to build and run integration tests or not") -mark_as_advanced(BOOST_MYSQL_INTEGRATION_TESTS) +# TODO: remove +add_executable(mycosql_example example/1_tutorial/1_sync.cpp) +target_link_libraries(mycosql_example PRIVATE Boost::mycosql) -# List of server features that the CI DB server does not support. -# Disables running some integration tests and examples -set(BOOST_MYSQL_DISABLED_SERVER_FEATURES "" CACHE STRING - "A CMake list of server features not supported by the CI server, for integration tests" -) -mark_as_advanced(BOOST_MYSQL_DISABLED_SERVER_FEATURES) +# # Don't run integration testing unless explicitly requested, since these require a running MySQL server +# option(BOOST_MYSQL_INTEGRATION_TESTS OFF "Whether to build and run integration tests or not") +# mark_as_advanced(BOOST_MYSQL_INTEGRATION_TESTS) + +# # List of server features that the CI DB server does not support. +# # Disables running some integration tests and examples +# set(BOOST_MYSQL_DISABLED_SERVER_FEATURES "" CACHE STRING +# "A CMake list of server features not supported by the CI server, for integration tests" +# ) +# mark_as_advanced(BOOST_MYSQL_DISABLED_SERVER_FEATURES) -# Don't build benchmarks unless explicitly requested, since these require the official -# MySQL and MariaDB client libraries -option(BOOST_MYSQL_BENCH OFF "Whether to build the benchmarks") -mark_as_advanced(BOOST_MYSQL_BENCH) +# # Don't build benchmarks unless explicitly requested, since these require the official +# # MySQL and MariaDB client libraries +# option(BOOST_MYSQL_BENCH OFF "Whether to build the benchmarks") +# mark_as_advanced(BOOST_MYSQL_BENCH) -# Examples and tests -if(BUILD_TESTING) - # Contains some functions to share code between examples and tests - include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake) +# # Examples and tests +# if(BUILD_TESTING) +# # Contains some functions to share code between examples and tests +# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake) - # Custom target tests; required by the Boost superproject - if(NOT TARGET tests) - add_custom_target(tests) - endif() +# # Custom target tests; required by the Boost superproject +# if(NOT TARGET tests) +# add_custom_target(tests) +# endif() - # Tests - add_subdirectory(test) +# # Tests +# add_subdirectory(test) - # All examples require a real server to run - if (BOOST_MYSQL_INTEGRATION_TESTS) - add_subdirectory(example) - endif() -endif() +# # All examples require a real server to run +# if (BOOST_MYSQL_INTEGRATION_TESTS) +# add_subdirectory(example) +# endif() +# endif() -if (BOOST_MYSQL_BENCH) - include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake) - add_subdirectory(bench) -endif() +# if (BOOST_MYSQL_BENCH) +# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake) +# add_subdirectory(bench) +# endif() diff --git a/example/1_tutorial/1_sync.cpp b/example/1_tutorial/1_sync.cpp index 4af5eb71f..79cf1eb7e 100644 --- a/example/1_tutorial/1_sync.cpp +++ b/example/1_tutorial/1_sync.cpp @@ -5,8 +5,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -//[example_tutorial_sync - /** * Creates a connection, establishes a session and * runs a simple "Hello world!" query. @@ -14,92 +12,71 @@ * This example uses synchronous functions and handles errors using exceptions. */ +#include #include #include -#include +#include #include -#include +#include +#include +#include +#include #include -//[tutorial_sync_namespaces namespace mysql = boost::mysql; -namespace asio = boost::asio; -//] +namespace corosio = boost::corosio; +namespace capy = boost::capy; -void main_impl(int argc, char** argv) +static void check_err(capy::io_result result) { - if (argc != 4) + if (result.ec) { - std::cerr << "Usage: " << argv[0] << " \n"; + std::cerr << "Error connecting: " << result.ec << ": " << result.get<1>().server_message() + << std::endl; exit(1); } +} - const char* hostname = argv[3]; - const char* username = argv[1]; - const char* password = argv[2]; - - //[tutorial_sync_connection - // The execution context, required to run I/O operations. - asio::io_context ctx; +capy::io_task<> main_impl() +{ + // if (argc != 4) + // { + // std::cerr << "Usage: " << argv[0] << " \n"; + // exit(1); + // } - // Represents a connection to the MySQL server. - mysql::any_connection conn(ctx); - //] + mysql::any_connection conn(co_await capy::this_coro::executor); - //[tutorial_sync_main - //[tutorial_sync_connect - // The hostname, username and password to use - mysql::connect_params params; - params.server_address.emplace_host_and_port(hostname); - params.username = username; - params.password = password; + mysql::connect_params params{ + .server_address = mysql::host_and_port("localhost"), + .username = "root", + .password = "", + }; // Connect to the server - conn.connect(params); - //] + check_err(co_await conn.connect(params)); - //[tutorial_sync_query // Issue the SQL query to the server const char* sql = "SELECT 'Hello world!'"; mysql::results result; - conn.execute(sql, result); - //] + check_err(co_await conn.execute(sql, result)); - //[tutorial_sync_results // Print the first field in the first row std::cout << result.rows().at(0).at(0) << std::endl; - //] - //[tutorial_sync_close - // Close the connection - conn.close(); - //] - //] + // // Close the connection + // conn.close(); + + co_return {}; } int main(int argc, char** argv) { - try - { - main_impl(argc, argv); - } - catch (const mysql::error_with_diagnostics& err) - { - // Some errors include additional diagnostics, like server-provided error messages. - // Security note: diagnostics::server_message may contain user-supplied values (e.g. the - // field value that caused the error) and is encoded using to the connection's character set - // (UTF-8 by default). Treat is as untrusted input. - std::cerr << "Error: " << err.what() << '\n' - << "Server diagnostics: " << err.get_diagnostics().server_message() << std::endl; - return 1; - } - catch (const std::exception& err) - { - std::cerr << "Error: " << err.what() << std::endl; - return 1; - } + corosio::io_context ctx; + capy::run_async(ctx.get_executor())(main_impl()); + ctx.run(); } //] diff --git a/include/boost/mysql.hpp b/include/boost/mysql.hpp index f50e1105c..eaff21458 100644 --- a/include/boost/mysql.hpp +++ b/include/boost/mysql.hpp @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/mysql/any_address.hpp b/include/boost/mysql/any_address.hpp index 9ee9c38d9..92d4604cd 100644 --- a/include/boost/mysql/any_address.hpp +++ b/include/boost/mysql/any_address.hpp @@ -9,11 +9,13 @@ #define BOOST_MYSQL_ANY_ADDRESS_HPP #include -#include #include +#include + #include +#include namespace boost { namespace mysql { @@ -187,7 +189,7 @@ class any_address * \par Exception safety * No-throw guarantee. */ - string_view hostname() const noexcept + std::string_view hostname() const noexcept { BOOST_ASSERT(type() == address_type::host_and_port); return impl_.address; @@ -219,7 +221,7 @@ class any_address * \par Exception safety * No-throw guarantee. */ - string_view unix_socket_path() const noexcept + std::string_view unix_socket_path() const noexcept { BOOST_ASSERT(type() == address_type::unix_path); return impl_.address; diff --git a/include/boost/mysql/any_connection.hpp b/include/boost/mysql/any_connection.hpp index 120575a3e..cac1a8a5b 100644 --- a/include/boost/mysql/any_connection.hpp +++ b/include/boost/mysql/any_connection.hpp @@ -8,40 +8,33 @@ #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 -#include -#include -#include +#include +#include +#include #include #include #include #include #include -#include -#include +#include +#include #include namespace boost { @@ -51,6 +44,7 @@ namespace mysql { template class static_execution_state; +class execution_state; class pipeline_request; class stage_response; @@ -59,26 +53,26 @@ class stage_response; */ struct any_connection_params { - /** - * \brief An external SSL context containing options to configure TLS. - * \details - * Relevant only for SSL connections (those that result on \ref - * any_connection::uses_ssl returning `true`). - * \n - * If the connection is configured to use TLS, an internal `asio::ssl::stream` - * object will be created. If this member is set to a non-null value, - * this internal object will be initialized using the passed context. - * This is the only way to configure TLS options in `any_connection`. - * \n - * If the connection is configured to use TLS and this member is `nullptr`, - * an internal `asio::ssl::context` object with suitable default options - * will be created. - * - * \par Object lifetimes - * If set to non-null, the pointee object must be kept alive until - * all \ref any_connection objects constructed from `*this` are destroyed. - */ - asio::ssl::context* ssl_context{}; + // /** + // * \brief An external SSL context containing options to configure TLS. + // * \details + // * Relevant only for SSL connections (those that result on \ref + // * any_connection::uses_ssl returning `true`). + // * \n + // * If the connection is configured to use TLS, an internal `asio::ssl::stream` + // * object will be created. If this member is set to a non-null value, + // * this internal object will be initialized using the passed context. + // * This is the only way to configure TLS options in `any_connection`. + // * \n + // * If the connection is configured to use TLS and this member is `nullptr`, + // * an internal `asio::ssl::context` object with suitable default options + // * will be created. + // * + // * \par Object lifetimes + // * If set to non-null, the pointee object must be kept alive until + // * all \ref any_connection objects constructed from `*this` are destroyed. + // */ + // asio::ssl::context* ssl_context{}; /** * \brief The initial size of the connection's buffer, in bytes. @@ -150,20 +144,22 @@ struct any_connection_params */ class any_connection { - detail::connection_impl impl_; - -#ifndef BOOST_MYSQL_DOXYGEN - friend struct detail::access; -#endif - - BOOST_MYSQL_DECL - static std::unique_ptr create_engine(asio::any_io_executor ex, asio::ssl::context* ctx); - - // Used by tests - any_connection(std::unique_ptr eng, any_connection_params params) - : impl_(params.initial_buffer_size, params.max_buffer_size, std::move(eng)) - { - } + struct impl_t; + std::unique_ptr impl_; + + // Private helpers for template functions + std::vector& shared_fields(); + + // Non-template I/O impl functions + capy::io_task start_execution_impl( + detail::any_execution_request req, + detail::execution_processor* proc + ); + capy::io_task read_some_rows_impl( + detail::execution_processor* proc, + detail::output_ref output + ); + capy::io_task read_resultset_head_impl(detail::execution_processor* proc); public: /** @@ -175,8 +171,8 @@ class any_connection * You can configure extra parameters, like the SSL context and buffer sizes, by passing * an \ref any_connection_params object to this constructor. */ - any_connection(boost::asio::any_io_executor ex, any_connection_params params = {}) - : any_connection(create_engine(std::move(ex), params.ssl_context), params) + template + any_connection(const Ex& ex, any_connection_params params = {}) : any_connection(ex.context(), params) { } @@ -192,29 +188,17 @@ class any_connection * This function participates in overload resolution only if `ExecutionContext` * satisfies the `ExecutionContext` requirements imposed by Boost.Asio. */ - template < - class ExecutionContext -#ifndef BOOST_MYSQL_DOXYGEN - , - class = typename std::enable_if().get_executor()), - asio::any_io_executor>::value>::type -#endif - > - any_connection(ExecutionContext& ctx, any_connection_params params = {}) - : any_connection(ctx.get_executor(), params) - { - } + any_connection(capy::execution_context& ctx, any_connection_params params = {}); /** * \brief Move constructor. */ - any_connection(any_connection&& other) = default; + any_connection(any_connection&& other) noexcept = default; /** * \brief Move assignment. */ - any_connection& operator=(any_connection&& rhs) = default; + any_connection& operator=(any_connection&& rhs) noexcept; #ifndef BOOST_MYSQL_DOXYGEN any_connection(const any_connection&) = delete; @@ -228,17 +212,7 @@ class any_connection * If you require a clean close, call \ref close or \ref async_close before the connection * is destroyed. */ - ~any_connection() = default; - - /// The executor type associated to this object. - using executor_type = asio::any_io_executor; - - /** - * \brief Retrieves the executor associated to this object. - * \par Exception safety - * No-throw guarantee. - */ - executor_type get_executor() noexcept { return impl_.get_engine().get_executor(); } + ~any_connection(); /** * \brief Returns whether the connection negotiated the use of SSL or not. @@ -253,7 +227,7 @@ class any_connection * \par Exception safety * No-throw guarantee. */ - bool uses_ssl() const noexcept { return impl_.ssl_active(); } + bool uses_ssl() const noexcept; /** * \brief Returns whether backslashes are being treated as escape sequences. @@ -278,7 +252,7 @@ class any_connection * \par Exception safety * No-throw guarantee. */ - bool backslash_escapes() const noexcept { return impl_.backslash_escapes(); } + bool backslash_escapes() const noexcept; /** * \brief Returns the character set used by this connection. @@ -290,11 +264,11 @@ class any_connection * \n * The following functions can modify the return value of this function: \n * \li Prior to connection, the character set is always unknown. - * \li \ref connect and \ref async_connect may set the current character set + * \li \ref connect may set the current character set * to a known value, depending on the requested collation. - * \li \ref set_character_set always and \ref async_set_character_set always - * set the current character set to the passed value. - * \li \ref reset_connection and \ref async_reset_connection always makes the current character + * \li \ref set_character_set always + * sets the current character set to the passed value. + * \li \ref reset_connection always makes the current character * unknown. * * \par Avoid changing the character set directly @@ -308,13 +282,11 @@ class any_connection * \par Exception safety * No-throw guarantee. */ - system::result current_character_set() const noexcept - { - return impl_.current_character_set(); - } + system::result current_character_set() const noexcept; /** - * \brief Returns format options suitable to format SQL according to the current connection configuration. + * \brief Returns format options suitable to format SQL according to the current connection + * configuration. * \details * If the current character set is known (as given by \ref current_character_set), returns * a value suitable to be passed to SQL formatting functions. Otherwise, returns an error. @@ -325,13 +297,7 @@ class any_connection * \par Exception safety * No-throw guarantee. */ - system::result format_opts() const noexcept - { - auto res = current_character_set(); - if (res.has_error()) - return res.error(); - return format_options{res.value(), backslash_escapes()}; - } + system::result format_opts() const noexcept; /** * \brief Returns the current metadata mode that this connection is using. @@ -341,7 +307,7 @@ class any_connection * * \returns The metadata mode that will be used for queries and statement executions. */ - metadata_mode meta_mode() const noexcept { return impl_.meta_mode(); } + metadata_mode meta_mode() const noexcept; /** * \brief Sets the metadata mode. @@ -356,14 +322,14 @@ class any_connection * * \param v The new metadata mode. */ - void set_meta_mode(metadata_mode v) noexcept { impl_.set_meta_mode(v); } + void set_meta_mode(metadata_mode v) noexcept; /** * \brief Retrieves the connection id associated to the current session. * \details * If a session has been established, returns its associated connection id. - * If no session has been established (i.e. \ref async_connect hasn't been called yet) - * or the session has been terminated (i.e. \ref async_close has been called), an empty + * If no session has been established (i.e. \ref connect hasn't been called yet) + * or the session has been terminated (i.e. \ref close has been called), an empty * optional is returned. * * The connection id is a 4 byte value that uniquely identifies a client session @@ -385,13 +351,13 @@ class any_connection * the official docs suggest (see * this changelog). * - * It is safe to call this function while an async operation is outstanding, except for \ref async_connect - * and \ref async_close. + * It is safe to call this function while an async operation is outstanding, except for \ref + * connect and \ref close. * * \par Exception safety * No-throw guarantee. */ - boost::optional connection_id() const noexcept { return impl_.connection_id(); } + boost::optional connection_id() const noexcept; /** * \brief Establishes a connection to a MySQL server. @@ -429,58 +395,7 @@ class any_connection * The default collation (`utf8mb4_general_ci`) is the only one guaranteed to be in the set of well-known * collations. */ - void connect(const connect_params& params, error_code& ec, diagnostics& diag) - { - impl_.connect_v2(params, ec, 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); - } - - /** - * \copydoc connect - * - * \par Object lifetimes - * params needs to be kept alive until the operation completes, as no - * copies will be made by the library. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_connect(const connect_params& params, diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_connect_v2_t) - { - return impl_.async_connect_v2(params, diag, std::forward(token)); - } - - /// \copydoc async_connect - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_connect(const connect_params& params, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_connect_v2_t) - { - return async_connect(params, impl_.shared_diag(), std::forward(token)); - } + capy::io_task connect(const connect_params& params); /** * \brief Executes a text query or prepared statement. @@ -498,84 +413,39 @@ class any_connection * Metadata in `result` will be populated according to `this->meta_mode()`. */ template - void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag) + capy::io_task execute(ExecutionRequest&& req, ResultsType& result) { - impl_.execute(std::forward(req), result, err, diag); + auto req_ref = detail::execution_request_traits>::make_request( + std::forward(req), + shared_fields() + ); + auto* results_ref = &detail::access::get_impl(result).get_interface(); + co_return co_await execute_impl(req_ref, results_ref); } - /// \copydoc execute - template - void execute(ExecutionRequest&& req, ResultsType& result) - { - error_code err; - diagnostics diag; - execute(std::forward(req), result, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } + capy::io_task execute_impl( + detail::any_execution_request req, + detail::execution_processor* proc + ); /** - * \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: + * \brief Prepares a statement server-side. + * \details + * `stmt` should be encoded using the connection's character set. * \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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. + * The returned statement has `valid() == true`. */ - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_RESULTS_TYPE ResultsType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_execute(ExecutionRequest&& req, ResultsType& result, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) - { - return async_execute( - std::forward(req), - result, - impl_.shared_diag(), - std::forward(token) - ); - } + capy::io_task prepare_statement(std::string_view stmt); - /// \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 = with_diagnostics_t> - auto async_execute( - ExecutionRequest&& req, - ResultsType& result, - diagnostics& diag, - CompletionToken&& token = {} - ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) - { - return impl_.async_execute( - std::forward(req), - result, - 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` + */ + capy::io_task close_statement(const statement& stmt); /** * \brief Starts a SQL execution as a multi-function operation. @@ -600,224 +470,17 @@ class any_connection * \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. - * \n */ template < BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution(ExecutionRequest&& req, ExecutionStateType& st, error_code& err, diagnostics& diag) - { - impl_.start_execution(std::forward(req), st, err, diag); - } - - /// \copydoc start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution(ExecutionRequest&& req, ExecutionStateType& st) - { - error_code err; - diagnostics diag; - start_execution(std::forward(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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_start_execution(ExecutionRequest&& req, ExecutionStateType& st, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< - ExecutionRequest&&, - ExecutionStateType, - CompletionToken&&>) + capy::io_task start_execution(ExecutionRequest&& req, ExecutionStateType& st) { - return async_start_execution( + auto req_ref = detail::execution_request_traits>::make_request( std::forward(req), - st, - impl_.shared_diag(), - std::forward(token) + shared_fields() ); - } - - /// \copydoc async_start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& st, - diagnostics& diag, - CompletionToken&& token = {} - ) - BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< - ExecutionRequest&&, - ExecutionStateType, - CompletionToken&&>) - { - return impl_.async_start_execution( - 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 impl_.run(detail::prepare_statement_algo_params{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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement)) - CompletionToken = with_diagnostics_t> - auto async_prepare_statement(string_view stmt, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) - { - return async_prepare_statement(stmt, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_prepare_statement - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::statement)) - CompletionToken = with_diagnostics_t> - auto async_prepare_statement(string_view stmt, diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) - { - return impl_.async_run( - detail::prepare_statement_algo_params{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) - { - impl_.run(impl_.make_params_close_statement(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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_close_statement(const statement& stmt, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) - { - return async_close_statement(stmt, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_close_statement - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_close_statement(const statement& stmt, diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) - { - return impl_ - .async_run(impl_.make_params_close_statement(stmt), diag, std::forward(token)); + co_return co_await start_execution_impl(req_ref, &detail::access::get_impl(st).get_interface()); } /** @@ -835,97 +498,7 @@ class any_connection * 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 impl_.run(impl_.make_params_read_some_rows(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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) - CompletionToken = with_diagnostics_t> - auto async_read_some_rows(execution_state& st, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) - { - return async_read_some_rows(st, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&) - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view)) - CompletionToken = with_diagnostics_t> - auto async_read_some_rows(execution_state& st, diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) - { - return impl_ - .async_run(impl_.make_params_read_some_rows(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 connection's buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in the - * constructor. 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 impl_.run(impl_.make_params_read_some_rows_static(st, output), err, diag); - } + capy::io_task read_some_rows(execution_state& st); /** * \brief Reads a batch of rows. @@ -946,145 +519,27 @@ class any_connection * 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 + * \par Extracting rows * The type `SpanElementType` must be the underlying row type for one of the types in the * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). * 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, `SpanElementType` - * must exactly be `underlying_row_t`. If this is not the case, a runtime error will be issued. + * given `static_execution_state`, when reading rows for the second resultset, + * `SpanElementType` must exactly be `underlying_row_t`. + * 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 connection's buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in the - * constructor. 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanElementType, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) - CompletionToken = with_diagnostics_t> - auto async_read_some_rows( + capy::io_task read_some_rows( static_execution_state& st, - span output, - CompletionToken&& token = {} + std::span output ) { - return async_read_some_rows(st, output, impl_.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 connection's buffer size. The bigger the buffer, - * the greater the batch size (up to a maximum). You can set the initial buffer size in the - * constructor. 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanElementType, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) - CompletionToken = with_diagnostics_t> - auto async_read_some_rows( - static_execution_state& st, - span output, - diagnostics& diag, - CompletionToken&& token = {} - ) - { - return impl_.async_run( - impl_.make_params_read_some_rows_static(st, output), - diag, - std::forward(token) + co_return co_await read_some_rows_impl( + &detail::access::get_impl(st).get_interface(), + detail::access::get_impl(st).make_output_ref(output) ); } -#endif /** * \brief Reads metadata for subsequent resultsets in a multi-resultset operation. @@ -1104,60 +559,11 @@ class any_connection * 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. - * \n */ template - void read_resultset_head(ExecutionStateType& st, error_code& err, diagnostics& diag) + capy::io_task read_resultset_head(ExecutionStateType& st) { - return impl_.run(impl_.make_params_read_resultset_head(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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_read_resultset_head(ExecutionStateType& st, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) - { - return async_read_resultset_head(st, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_resultset_head - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_read_resultset_head(ExecutionStateType& st, diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) - { - return impl_ - .async_run(impl_.make_params_read_resultset_head(st), diag, std::forward(token)); + co_return co_await read_resultset_head_impl(&detail::access::get_impl(st).get_interface()); } /** @@ -1181,62 +587,7 @@ class any_connection * \par Object lifetimes * `charset` will be copied as required, and does not need to be kept alive. */ - void set_character_set(const character_set& charset, error_code& err, diagnostics& diag) - { - impl_.run(detail::set_character_set_algo_params{charset}, err, diag); - } - - /// \copydoc set_character_set - void set_character_set(const character_set& charset) - { - error_code err; - diagnostics diag; - set_character_set(charset, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc set_character_set - * \details - * \n - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_set_character_set(const character_set& charset, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_set_character_set_t) - { - return async_set_character_set(charset, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_set_character_set - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_set_character_set( - const character_set& charset, - diagnostics& diag, - CompletionToken&& token = {} - ) BOOST_MYSQL_RETURN_TYPE(detail::async_set_character_set_t) - { - return impl_.async_run( - detail::set_character_set_algo_params{charset}, - diag, - std::forward(token) - ); - } + capy::io_task set_character_set(const character_set& charset); /** * \brief Checks whether the server is alive. @@ -1249,52 +600,7 @@ class any_connection * in a long-running query, the ping request won't be answered until the query is * finished. */ - void ping(error_code& err, diagnostics& diag) { impl_.run(detail::ping_algo_params{}, 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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_ping(CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) - { - return async_ping(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_ping - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_ping(diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) - { - return impl_.async_run(detail::ping_algo_params{}, diag, std::forward(token)); - } + capy::io_task ping(); /** * \brief Resets server-side session state, like variables and prepared statements. @@ -1322,65 +628,15 @@ class any_connection * This function will restore the connection's character set and collation **to the server's default**, * and not to the one specified during connection establishment. Some servers have `latin1` as their * default character set, which is not usually what you want. Since there is no way to know this - * character set, \ref current_character_set will return `nullptr` after the operation succeeds. - * We recommend always using \ref set_character_set or \ref async_set_character_set after calling this - * function. + * character set, \ref current_character_set will return an error after the operation succeeds. + * We recommend always using \ref set_character_set after calling this function. * \n * You can find the character set that your server will use after the reset by running: * \code * "SELECT @@global.character_set_client, @@global.character_set_results;" * \endcode */ - void reset_connection(error_code& err, diagnostics& diag) - { - impl_.run(detail::reset_connection_algo_params{}, 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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_reset_connection(CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) - { - return async_reset_connection(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_reset_connection - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken = with_diagnostics_t> - auto async_reset_connection(diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) - { - return impl_ - .async_run(detail::reset_connection_algo_params{}, diag, std::forward(token)); - } + capy::io_task reset_connection(); /** * \brief Cleanly closes the connection to the server. @@ -1401,55 +657,7 @@ class any_connection * perform a transport-layer close. This doesn't cause any resource leaks, but may * cause warnings to be written to the server logs. */ - void close(error_code& err, diagnostics& diag) - { - impl_.run(detail::close_connection_algo_params{}, err, 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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_close(CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) - { - return async_close(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_close - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_close(diagnostics& diag, CompletionToken&& token = {}) - BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) - { - return this->impl_ - .async_run(detail::close_connection_algo_params{}, diag, std::forward(token)); - } + capy::io_task close(); /** * \brief Runs a set of pipelined requests. @@ -1472,78 +680,10 @@ class any_connection * Successive stages will be marked as failed with the fatal error. The server may or may * not have processed such stages. */ - void run_pipeline( - const pipeline_request& req, - std::vector& res, - error_code& err, - diagnostics& diag - ) - { - impl_.run(impl_.make_params_pipeline(req, res), err, diag); - } - - /// \copydoc run_pipeline - void run_pipeline(const pipeline_request& req, std::vector& res) - { - error_code err; - diagnostics diag; - run_pipeline(req, res, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc run_pipeline - * \details - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - * - * \par Object lifetimes - * The request and response objects must be kept alive and should not be modified - * until the operation completes. - */ - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_run_pipeline( - const pipeline_request& req, - std::vector& res, - CompletionToken&& token = {} - ) BOOST_MYSQL_RETURN_TYPE(detail::async_run_pipeline_t) - { - return async_run_pipeline(req, res, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_run_pipeline - template < - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) - CompletionToken = with_diagnostics_t> - auto async_run_pipeline( - const pipeline_request& req, - std::vector& res, - diagnostics& diag, - CompletionToken&& token = {} - ) BOOST_MYSQL_RETURN_TYPE(detail::async_run_pipeline_t) - { - return this->impl_ - .async_run(impl_.make_params_pipeline(req, res), diag, std::forward(token)); - } + capy::io_task run_pipeline(const pipeline_request& req, std::vector& res); }; } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif - #endif diff --git a/include/boost/mysql/blob_view.hpp b/include/boost/mysql/blob_view.hpp index 5a3fb4e23..4ed29715f 100644 --- a/include/boost/mysql/blob_view.hpp +++ b/include/boost/mysql/blob_view.hpp @@ -8,13 +8,13 @@ #ifndef BOOST_MYSQL_BLOB_VIEW_HPP #define BOOST_MYSQL_BLOB_VIEW_HPP -#include +#include namespace boost { namespace mysql { /// Non-owning type used to represent binary blobs. -using blob_view = boost::span; +using blob_view = std::span; } // namespace mysql } // namespace boost diff --git a/include/boost/mysql/character_set.hpp b/include/boost/mysql/character_set.hpp index 7aeefed06..12efe220d 100644 --- a/include/boost/mysql/character_set.hpp +++ b/include/boost/mysql/character_set.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include @@ -50,7 +50,7 @@ struct character_set * \n * This function must not throw exceptions or have side effects. */ - std::size_t (*next_char)(span); + std::size_t (*next_char)(std::span); }; /// The utf8mb4 character set (the one you should use by default). @@ -84,8 +84,5 @@ struct format_options } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/client_errc.hpp b/include/boost/mysql/client_errc.hpp index 91b59bdbe..1d54e30b4 100644 --- a/include/boost/mysql/client_errc.hpp +++ b/include/boost/mysql/client_errc.hpp @@ -201,8 +201,5 @@ struct is_error_code_enum<::boost::mysql::client_errc> } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/column_type.hpp b/include/boost/mysql/column_type.hpp index a0e776dbc..79217a446 100644 --- a/include/boost/mysql/column_type.hpp +++ b/include/boost/mysql/column_type.hpp @@ -63,8 +63,5 @@ std::ostream& operator<<(std::ostream& os, column_type t); } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/common_server_errc.hpp b/include/boost/mysql/common_server_errc.hpp index cdc9c1484..52ad13e22 100644 --- a/include/boost/mysql/common_server_errc.hpp +++ b/include/boost/mysql/common_server_errc.hpp @@ -5125,8 +5125,5 @@ struct is_error_code_enum<::boost::mysql::common_server_errc> } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/connect_params.hpp b/include/boost/mysql/connect_params.hpp index b21ad2d8d..ce2ce44ce 100644 --- a/include/boost/mysql/connect_params.hpp +++ b/include/boost/mysql/connect_params.hpp @@ -10,10 +10,10 @@ #include #include -#include #include #include +#include namespace boost { namespace mysql { diff --git a/include/boost/mysql/connection.hpp b/include/boost/mysql/connection.hpp deleted file mode 100644 index 30d077710..000000000 --- a/include/boost/mysql/connection.hpp +++ /dev/null @@ -1,1127 +0,0 @@ -// -// Copyright (c) 2019-2025 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_CONNECTION_HPP -#define BOOST_MYSQL_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 - -/// The Boost libraries namespace. -namespace boost { -/// Boost.MySQL library namespace. -namespace mysql { - -// Forward declarations -template -class static_execution_state; - -/** - * \brief (Legacy) A connection to a MySQL server. - * \details - * Represents a templated connection to a MySQL server. - * - * `connection` owns a `Stream` object that - * is accessed by functions involving network operations, as well as session state. You can access - * the stream using \ref connection::stream, and its executor via \ref connection::get_executor. The - * executor used by this object is always the same as the underlying stream. - * - * \par Single outstanding async operation per connection - * At any given point in time, only one async operation can be outstanding - * per connection. If an async operation is initiated while another one is in progress, - * it will fail with \ref client_errc::operation_in_progress. - * - * \par Thread safety - * Distinct objects: safe. \n - * Shared objects: unsafe. \n - * This class is not thread-safe: for a single object, if you - * call its member functions concurrently from separate threads, you will get a race condition. - * - * \par Legacy - * New code should use \ref any_connection instead of this class, as it's simpler to use - * and provides the same level of performance. - */ -template -class connection -{ - detail::connection_impl impl_; - -public: - /** - * \brief Initializing constructor. - * \details - * As part of the initialization, an internal `Stream` object is created. - * - * \par Exception safety - * Basic guarantee. Throws if the `Stream` constructor throws - * or if memory allocation for internal state fails. - * - * \param args Arguments to be forwarded to the `Stream` constructor. - */ - template < - class... Args, - class EnableIf = typename std::enable_if::value>::type> - connection(Args&&... args) : connection(buffer_params(), std::forward(args)...) - { - } - - /** - * \brief Initializing constructor with buffer params. - * \details - * As part of the initialization, an internal `Stream` object is created. - * - * \par Exception safety - * Basic guarantee. Throws if the `Stream` constructor throws - * or if memory allocation for internal state fails. - * - * \param buff_params Specifies initial sizes for internal buffers. - * \param args Arguments to be forwarded to the `Stream` constructor. - */ - template < - class... Args, - class EnableIf = typename std::enable_if::value>::type> - connection(const buffer_params& buff_params, Args&&... args) - : impl_( - buff_params.initial_read_size(), - static_cast(-1), - detail::make_engine(std::forward(args)...) - ) - { - } - - /** - * \brief Move constructor. - */ - connection(connection&& other) = default; - - /** - * \brief Move assignment. - */ - connection& operator=(connection&& rhs) = default; - -#ifndef BOOST_MYSQL_DOXYGEN - connection(const connection&) = delete; - connection& operator=(const connection&) = delete; -#endif - - /// The executor type associated to this object. - using executor_type = typename Stream::executor_type; - - /// Retrieves the executor associated to this object. - executor_type get_executor() { return stream().get_executor(); } - - /// The `Stream` type this connection is using. - using stream_type = Stream; - - /** - * \brief Retrieves the underlying Stream object. - * \details - * - * \par Exception safety - * No-throw guarantee. - */ - Stream& stream() noexcept { return detail::stream_from_engine(impl_.get_engine()); } - - /** - * \brief Retrieves the underlying Stream object. - * \details - * - * \par Exception safety - * No-throw guarantee. - */ - const Stream& stream() const noexcept { return detail::stream_from_engine(impl_.get_engine()); } - - /** - * \brief Returns whether the connection negotiated the use of SSL or not. - * \details - * This function can be used to determine whether you are using a SSL - * connection or not when using SSL negotiation. - * \n - * This function always returns `false` if the underlying - * stream does not support SSL. This function always returns `false` - * for connections that haven't been - * established yet (handshake not run yet). If the handshake fails, - * the return value is undefined. - * - * \par Exception safety - * No-throw guarantee. - * - * \returns Whether the connection is using SSL. - */ - bool uses_ssl() const noexcept { return impl_.ssl_active(); } - - /// \copydoc any_connection::meta_mode - metadata_mode meta_mode() const noexcept { return impl_.meta_mode(); } - - /// \copydoc any_connection::set_meta_mode - void set_meta_mode(metadata_mode v) noexcept { impl_.set_meta_mode(v); } - - /** - * \brief Establishes a connection to a MySQL server. - * \details - * This function is only available if `Stream` satisfies the - * `SocketStream` concept. - * \n - * Connects the underlying stream and performs the handshake - * with the server. The underlying stream is closed in case of error. Prefer - * this function to \ref connection::handshake. - * \n - * If using a SSL-capable stream, the SSL handshake will be performed by this function. - * \n - * `endpoint` should be convertible to `Stream::lowest_layer_type::endpoint_type`. - */ - template - void connect( - const EndpointType& endpoint, - const handshake_params& params, - error_code& ec, - diagnostics& diag - ) - { - static_assert( - detail::is_socket_stream::value, - "connect can only be used if Stream satisfies the SocketStream concept" - ); - impl_.connect(endpoint, params, ec, diag); - } - - /// \copydoc connect - template - void connect(const EndpointType& endpoint, const handshake_params& params) - { - static_assert( - detail::is_socket_stream::value, - "connect can only be used if Stream satisfies the SocketStream concept" - ); - error_code err; - diagnostics diag; - connect(endpoint, params, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc connect - * \par Object lifetimes - * The strings pointed to by `params` should be kept alive by the caller - * until the operation completes, as no copy is made by the library. - * `endpoint` is copied as required and doesn't need to be kept alive. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template < - typename EndpointType, - 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_connect( - const EndpointType& endpoint, - const handshake_params& params, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - static_assert( - detail::is_socket_stream::value, - "async_connect can only be used if Stream satisfies the SocketStream concept" - ); - return async_connect(endpoint, params, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_connect - template < - typename EndpointType, - 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_connect( - const EndpointType& endpoint, - const handshake_params& params, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - static_assert( - detail::is_socket_stream::value, - "async_connect can only be used if Stream satisfies the SocketStream concept" - ); - return impl_.async_connect( - endpoint, - params, - diag, - std::forward(token) - ); - } - - /** - * \brief Performs the MySQL-level handshake. - * \details - * Does not connect the underlying stream. - * If the `Stream` template parameter fulfills the `SocketConnection` - * requirements, use \ref connection::connect instead of this function. - * \n - * If using a SSL-capable stream, the SSL handshake will be performed by this function. - */ - void handshake(const handshake_params& params, error_code& ec, diagnostics& diag) - { - impl_.run(impl_.make_params_handshake(params), ec, diag); - } - - /// \copydoc handshake - void handshake(const handshake_params& params) - { - error_code err; - diagnostics diag; - handshake(params, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc handshake - * \par Object lifetimes - * The strings pointed to by `params` should be kept alive by the caller - * until the operation completes, as no copy is made by the library. - * - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template - auto async_handshake( - const handshake_params& params, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_handshake_t) - { - return async_handshake(params, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_handshake - template - auto async_handshake( - const handshake_params& params, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_handshake_t) - { - return impl_ - .async_run(impl_.make_params_handshake(params), diag, std::forward(token)); - } - - /// \copydoc any_connection::execute - template - void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag) - { - impl_.execute(std::forward(req), result, err, diag); - } - - /// \copydoc execute - template - void execute(ExecutionRequest&& req, ResultsType& result) - { - error_code err; - diagnostics diag; - execute(std::forward(req), result, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /// \copydoc any_connection::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)> - auto async_execute( - ExecutionRequest&& req, - ResultsType& result, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) - { - return async_execute( - std::forward(req), - result, - impl_.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)> - auto async_execute( - ExecutionRequest&& req, - ResultsType& result, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_execute_t) - { - return impl_.async_execute( - std::forward(req), - result, - diag, - std::forward(token) - ); - } - - /// \copydoc any_connection::start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution(ExecutionRequest&& req, ExecutionStateType& st, error_code& err, diagnostics& diag) - { - impl_.start_execution(std::forward(req), st, err, diag); - } - - /// \copydoc start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType> - void start_execution(ExecutionRequest&& req, ExecutionStateType& st) - { - error_code err; - diagnostics diag; - start_execution(std::forward(req), st, err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /// \copydoc any_connection::async_start_execution - template < - BOOST_MYSQL_EXECUTION_REQUEST ExecutionRequest, - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - auto async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< - ExecutionRequest&&, - ExecutionStateType, - CompletionToken&&>) - { - return async_start_execution( - std::forward(req), - st, - impl_.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(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - auto async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - BOOST_MYSQL_RETURN_TYPE(detail::async_start_execution_t< - ExecutionRequest&&, - ExecutionStateType, - CompletionToken&&>) - { - return impl_.async_start_execution( - std::forward(req), - st, - diag, - std::forward(token) - ); - } - - /// \copydoc any_connection::prepare_statement - statement prepare_statement(string_view stmt, error_code& err, diagnostics& diag) - { - return impl_.run(detail::prepare_statement_algo_params{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 any_connection::async_prepare_statement - template - auto async_prepare_statement( - string_view stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) - { - return async_prepare_statement(stmt, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_prepare_statement - template - auto async_prepare_statement( - string_view stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_prepare_statement_t) - { - return impl_.async_run( - detail::prepare_statement_algo_params{stmt}, - diag, - std::forward(token) - ); - } - - /// \copydoc any_connection::close_statement - void close_statement(const statement& stmt, error_code& err, diagnostics& diag) - { - impl_.run(impl_.make_params_close_statement(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 any_connection::async_close_statement - template - auto async_close_statement( - const statement& stmt, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) - { - return async_close_statement(stmt, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_close_statement - template - auto async_close_statement( - const statement& stmt, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_statement_t) - { - return impl_ - .async_run(impl_.make_params_close_statement(stmt), diag, std::forward(token)); - } - - /// \copydoc any_connection::read_some_rows - rows_view read_some_rows(execution_state& st, error_code& err, diagnostics& diag) - { - return impl_.run(impl_.make_params_read_some_rows(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 any_connection::async_read_some_rows(execution_state&,CompletionToken&&) - template - auto async_read_some_rows( - execution_state& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) - { - return async_read_some_rows(st, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_some_rows(execution_state&,CompletionToken&&) - template - auto async_read_some_rows( - execution_state& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_some_rows_dynamic_t) - { - return impl_ - .async_run(impl_.make_params_read_some_rows(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 connection's 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 impl_.run(impl_.make_params_read_some_rows_static(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 connection's 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 connection's 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanElementType, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - 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 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return async_read_some_rows(st, output, impl_.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 connection's 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 - * The type `SpanElementType` must be the underlying row type for one of the types in the - * `StaticRow` parameter pack (i.e., one of the types in `underlying_row_t...`). - * 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, `SpanElementType` - * must exactly be `underlying_row_t`. 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 Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - * - * \par Object lifetimes - * The storage that `output` references must be kept alive until the operation completes. - */ - template < - class SpanElementType, - class... StaticRow, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, std::size_t)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - 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 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) - { - return impl_.async_run( - impl_.make_params_read_some_rows_static(st, output), - diag, - std::forward(token) - ); - } -#endif - - /// \copydoc any_connection::read_resultset_head - template - void read_resultset_head(ExecutionStateType& st, error_code& err, diagnostics& diag) - { - return impl_.run(impl_.make_params_read_resultset_head(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 any_connection::async_read_resultset_head - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - auto async_read_resultset_head( - ExecutionStateType& st, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) - { - return async_read_resultset_head(st, impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_read_resultset_head - template < - BOOST_MYSQL_EXECUTION_STATE_TYPE ExecutionStateType, - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - auto async_read_resultset_head( - ExecutionStateType& st, - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_read_resultset_head_t) - { - return impl_ - .async_run(impl_.make_params_read_resultset_head(st), diag, std::forward(token)); - } - - /// \copydoc any_connection::ping - void ping(error_code& err, diagnostics& diag) { impl_.run(detail::ping_algo_params{}, 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 any_connection::async_ping - template - auto async_ping(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) - { - return async_ping(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_ping - template - auto async_ping( - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_ping_t) - { - return impl_.async_run(detail::ping_algo_params{}, 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. - * - * \par Warning on character sets - * This function will restore the connection's character set and collation **to the server's default**, - * and not to the one specified during connection establishment. Some servers have `latin1` as their - * default character set, which is not usually what you want. Use a `SET NAMES` statement after using - * this function to be sure. - * \n - * You can find the character set that your server will use after reset by running: - * \code - * "SELECT @@global.character_set_client, @@global.character_set_results;" - * \endcode - */ - void reset_connection(error_code& err, diagnostics& diag) - { - impl_.run(detail::reset_connection_algo_params{}, 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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template - auto async_reset_connection(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) - { - return async_reset_connection(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_reset_connection - template - auto async_reset_connection( - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_reset_connection_t) - { - return impl_ - .async_run(detail::reset_connection_algo_params{}, 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. - * \n - */ - void close(error_code& err, diagnostics& diag) - { - static_assert( - detail::is_socket_stream::value, - "close can only be used if Stream satisfies the SocketStream concept" - ); - impl_.run(detail::close_connection_algo_params{}, err, diag); - } - - /// \copydoc close - void close() - { - static_assert( - detail::is_socket_stream::value, - "close can only be used if Stream satisfies the SocketStream concept" - ); - 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)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template - auto async_close(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) - { - static_assert( - detail::is_socket_stream::value, - "async_close can only be used if Stream satisfies the SocketStream concept" - ); - return async_close(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_close - template - auto async_close( - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_close_connection_t) - { - static_assert( - detail::is_socket_stream::value, - "async_close can only be used if Stream satisfies the SocketStream concept" - ); - return impl_ - .async_run(detail::close_connection_algo_params{}, diag, std::forward(token)); - } - - /** - * \brief Notifies the MySQL server that the client wants to end the session and shutdowns SSL. - * \details Sends a quit request to the MySQL server. If the connection is using SSL, - * this function will also perform the SSL shutdown. You should - * close the underlying physical connection after calling this function. - * \n - * If the `Stream` template parameter fulfills the `SocketConnection` - * requirements, use \ref connection::close instead of this function, - * as it also takes care of closing the underlying stream. - */ - void quit(error_code& err, diagnostics& diag) - { - impl_.run(detail::quit_connection_algo_params{}, err, diag); - } - - /// \copydoc quit - void quit() - { - error_code err; - diagnostics diag; - quit(err, diag); - detail::throw_on_error_loc(err, diag, BOOST_CURRENT_LOCATION); - } - - /** - * \copydoc quit - * \details - * \par Handler signature - * The handler signature for this operation is `void(boost::mysql::error_code)`. - * - * \par Executor - * Intermediate completion handlers, as well as the final handler, are executed using - * `token`'s associated executor, or `this->get_executor()` if the token doesn't have an associated - * executor. - * - * If the final handler has an associated immediate executor, and the operation - * completes immediately, the final handler is dispatched to it. - * Otherwise, the final handler is called as if it was submitted using `asio::post`, - * and is never be called inline from within this function. - */ - template - auto async_quit(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - BOOST_MYSQL_RETURN_TYPE(detail::async_quit_connection_t) - { - return async_quit(impl_.shared_diag(), std::forward(token)); - } - - /// \copydoc async_quit - template - auto async_quit( - diagnostics& diag, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type) - ) BOOST_MYSQL_RETURN_TYPE(detail::async_quit_connection_t) - { - return impl_ - .async_run(detail::quit_connection_algo_params{}, diag, std::forward(token)); - } - - /** - * \brief Rebinds the connection type to another executor. - * \details - * The `Stream` type must either provide a `rebind_executor` - * member with the same semantics, or be an instantiation of `boost::asio::ssl::stream` with - * a `Stream` type providing a `rebind_executor` member. - */ - template - struct rebind_executor - { - /// The connection type when rebound to the specified executor. - using other = connection::type>; - }; -}; - -} // namespace mysql -} // namespace boost - -#endif diff --git a/include/boost/mysql/constant_string_view.hpp b/include/boost/mysql/constant_string_view.hpp index 5a19f0b85..94164b711 100644 --- a/include/boost/mysql/constant_string_view.hpp +++ b/include/boost/mysql/constant_string_view.hpp @@ -8,12 +8,11 @@ #ifndef BOOST_MYSQL_CONSTANT_STRING_VIEW_HPP #define BOOST_MYSQL_CONSTANT_STRING_VIEW_HPP -#include - #include #include +#include #include namespace boost { @@ -31,11 +30,11 @@ namespace mysql { */ class constant_string_view { - string_view impl_; + std::string_view impl_; #ifndef BOOST_MYSQL_DOXYGEN - constexpr constant_string_view(string_view value, int) noexcept : impl_(value) {} - friend constexpr constant_string_view runtime(string_view) noexcept; + constexpr constant_string_view(std::string_view value, int) noexcept : impl_(value) {} + friend constexpr constant_string_view runtime(std::string_view) noexcept; #endif public: @@ -56,14 +55,14 @@ class constant_string_view * No-throw guarantee. * * \par Object lifetimes - * Ownership is not transferred to the constructed object. As with `string_view`, + * Ownership is not transferred to the constructed object. As with `std::string_view`, * the user is responsible for keeping the original character buffer alive. */ template < class T #ifndef BOOST_MYSQL_DOXYGEN , - class = typename std::enable_if::value>::type + class = typename std::enable_if::value>::type #endif > BOOST_MYSQL_CONSTEVAL constant_string_view(const T& value) noexcept : impl_(value) @@ -79,7 +78,7 @@ class constant_string_view * \par Object lifetimes * The returned view has the same lifetime rules as `*this`. */ - constexpr string_view get() const noexcept { return impl_; } + constexpr std::string_view get() const noexcept { return impl_; } }; /** @@ -97,7 +96,10 @@ class constant_string_view * \par Object lifetimes * The returned value has the same lifetime semantics as the passed view. */ -constexpr constant_string_view runtime(string_view value) noexcept { return constant_string_view(value, 0); } +constexpr constant_string_view runtime(std::string_view value) noexcept +{ + return constant_string_view(value, 0); +} } // namespace mysql } // namespace boost diff --git a/include/boost/mysql/date.hpp b/include/boost/mysql/date.hpp index b1096f19b..db43f8b71 100644 --- a/include/boost/mysql/date.hpp +++ b/include/boost/mysql/date.hpp @@ -302,8 +302,5 @@ BOOST_INLINE_CONSTEXPR date max_date{9999u, 12u, 31u}; } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/datetime.hpp b/include/boost/mysql/datetime.hpp index bd966d789..39a96f52a 100644 --- a/include/boost/mysql/datetime.hpp +++ b/include/boost/mysql/datetime.hpp @@ -403,8 +403,5 @@ BOOST_CXX14_CONSTEXPR boost::mysql::datetime::datetime(time_point tp) hour_ = static_cast(num_hours.count()); } -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/algo_params.hpp b/include/boost/mysql/detail/algo_params.hpp index 427bd9b37..bce56b200 100644 --- a/include/boost/mysql/detail/algo_params.hpp +++ b/include/boost/mysql/detail/algo_params.hpp @@ -8,17 +8,17 @@ #ifndef BOOST_MYSQL_DETAIL_ALGO_PARAMS_HPP #define BOOST_MYSQL_DETAIL_ALGO_PARAMS_HPP +#include #include #include -#include #include #include -#include - #include #include +#include +#include #include namespace boost { @@ -36,8 +36,7 @@ struct pipeline_request_stage; struct connect_algo_params { - const void* server_address; // Points to an any_address or an endpoint for the corresponding stream. For - // the templated connection, only valid until the first yield! + const any_address* server_address; handshake_params hparams; bool secure_channel; // Are we using UNIX sockets or any other secure channel? @@ -92,7 +91,7 @@ struct read_some_rows_dynamic_algo_params struct prepare_statement_algo_params { - string_view stmt_sql; + std::string_view stmt_sql; using result_type = statement; }; @@ -133,8 +132,8 @@ struct close_connection_algo_params struct run_pipeline_algo_params { - span request_buffer; - span request_stages; + std::span request_buffer; + std::span request_stages; std::vector* response; using result_type = void; diff --git a/include/boost/mysql/detail/any_execution_request.hpp b/include/boost/mysql/detail/any_execution_request.hpp index ed590b644..4449a8a35 100644 --- a/include/boost/mysql/detail/any_execution_request.hpp +++ b/include/boost/mysql/detail/any_execution_request.hpp @@ -9,11 +9,10 @@ #define BOOST_MYSQL_DETAIL_ANY_EXECUTION_REQUEST_HPP #include -#include - -#include #include +#include +#include #include #include @@ -36,20 +35,20 @@ struct any_execution_request union data_t { - string_view query; + std::string_view query; struct query_with_params_t { constant_string_view query; - span args; + std::span args; } query_with_params; struct stmt_t { std::uint32_t stmt_id; std::uint16_t num_params; - span params; + std::span params; } stmt; - data_t(string_view q) noexcept : query(q) {} + data_t(std::string_view q) noexcept : query(q) {} data_t(query_with_params_t v) noexcept : query_with_params(v) {} data_t(stmt_t v) noexcept : stmt(v) {} }; @@ -57,7 +56,7 @@ struct any_execution_request type_t type; data_t data; - any_execution_request(string_view q) noexcept : type(type_t::query), data(q) {} + any_execution_request(std::string_view q) noexcept : type(type_t::query), data(q) {} any_execution_request(data_t::query_with_params_t v) noexcept : type(type_t::query_with_params), data(v) { } @@ -74,9 +73,14 @@ struct execution_request_traits : no_execution_request_traits }; template -struct execution_request_traits::value>::type> +struct execution_request_traits< + T, + typename std::enable_if::value>::type> { - static any_execution_request make_request(string_view input, std::vector&) { return input; } + static any_execution_request make_request(std::string_view input, std::vector&) + { + return input; + } }; } // namespace detail diff --git a/include/boost/mysql/detail/character_set.hpp b/include/boost/mysql/detail/character_set.hpp index a0f165e08..356cc4158 100644 --- a/include/boost/mysql/detail/character_set.hpp +++ b/include/boost/mysql/detail/character_set.hpp @@ -10,7 +10,7 @@ #include -#include +#include #include @@ -18,8 +18,8 @@ namespace boost { namespace mysql { namespace detail { -inline std::size_t next_char_ascii(span input) { return input[0] <= 0x7f ? 1 : 0; } -BOOST_MYSQL_DECL std::size_t next_char_utf8mb4(span input); +inline std::size_t next_char_ascii(std::span input) { return input[0] <= 0x7f ? 1 : 0; } +BOOST_MYSQL_DECL std::size_t next_char_utf8mb4(std::span input); } // namespace detail } // namespace mysql diff --git a/include/boost/mysql/detail/coldef_view.hpp b/include/boost/mysql/detail/coldef_view.hpp index b5d2eb80a..b4d0a0890 100644 --- a/include/boost/mysql/detail/coldef_view.hpp +++ b/include/boost/mysql/detail/coldef_view.hpp @@ -9,9 +9,9 @@ #define BOOST_MYSQL_DETAIL_COLDEF_VIEW_HPP #include -#include #include +#include namespace boost { namespace mysql { @@ -19,11 +19,11 @@ namespace detail { struct coldef_view { - string_view database; - string_view table; - string_view org_table; - string_view name; - string_view org_name; + std::string_view database; + std::string_view table; + std::string_view org_table; + std::string_view name; + std::string_view org_name; std::uint16_t collation_id; std::uint32_t column_length; // maximum length of the field column_type type; diff --git a/include/boost/mysql/detail/config.hpp b/include/boost/mysql/detail/config.hpp index 3779d8e3e..c7c0748ce 100644 --- a/include/boost/mysql/detail/config.hpp +++ b/include/boost/mysql/detail/config.hpp @@ -29,13 +29,8 @@ #define BOOST_MYSQL_CONSTEVAL constexpr #endif -// Separate build -#if defined(BOOST_MYSQL_SEPARATE_COMPILATION) - #define BOOST_MYSQL_DECL -#else - #define BOOST_MYSQL_HEADER_ONLY - #define BOOST_MYSQL_DECL inline -#endif +// Separate build (TODO) +#define BOOST_MYSQL_DECL // Auto return type. Having this as a macro helps the documentation tool. #ifdef BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION diff --git a/include/boost/mysql/detail/connection_impl.hpp b/include/boost/mysql/detail/connection_impl.hpp deleted file mode 100644 index e9e405074..000000000 --- a/include/boost/mysql/detail/connection_impl.hpp +++ /dev/null @@ -1,670 +0,0 @@ -// -// Copyright (c) 2019-2025 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_DETAIL_CONNECTION_IMPL_HPP -#define BOOST_MYSQL_DETAIL_CONNECTION_IMPL_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 -#include -#include -#include - -namespace boost { -namespace mysql { - -// Forward decl -template -class static_execution_state; - -struct character_set; -class pipeline_request; - -namespace detail { - -// -// Helpers to interact with connection_state, without including its definition -// -class connection_state; - -struct connection_state_deleter -{ - BOOST_MYSQL_DECL void operator()(connection_state*) const; -}; - -BOOST_MYSQL_DECL std::vector& get_shared_fields(connection_state&); - -template -any_resumable_ref setup(connection_state&, diagnostics&, const AlgoParams&); - -// Note: AlgoParams should have !is_void_result -template -typename AlgoParams::result_type get_result(const connection_state&); - -// -// helpers to run algos -// -template -using has_void_result = std::is_same; - -template -struct completion_signature_impl; - -template -struct completion_signature_impl -{ - // Using typedef to workaround a msvc 14.1 bug - typedef void(type)(error_code); -}; - -template -struct completion_signature_impl -{ - // Using typedef to workaround a msvc 14.1 bug - typedef void(type)(error_code, typename AlgoParams::result_type); -}; - -template -using completion_signature_t = typename completion_signature_impl< - AlgoParams, - has_void_result::value>::type; - -// Intermediate handler -template -struct generic_algo_fn -{ - static_assert(!has_void_result::value, "Internal error: result_type should be non-void"); - - using result_t = typename AlgoParams::result_type; - - template - void operator()(Handler&& handler, error_code ec) - { - std::move(handler)(ec, ec ? result_t{} : get_result(*st)); - } - - connection_state* st; -}; - -// Note: the 1st async_initiate arg should be a diagnostics*, -// so completion tokens knowing how Boost.MySQL work can operate -class connection_impl -{ - std::unique_ptr engine_; - std::unique_ptr st_; - - asio::any_io_executor get_executor() const { return engine_->get_executor(); } - - // Helper for execution requests - template - static auto make_request(T&& input, connection_state& st) - -> decltype(execution_request_traits::type>::make_request( - std::forward(input), - get_shared_fields(st) - )) - { - return execution_request_traits::type>::make_request( - std::forward(input), - get_shared_fields(st) - ); - } - - // Generic algorithm - template - typename AlgoParams::result_type run_impl( - AlgoParams params, - error_code& ec, - diagnostics& diag, - std::true_type /* has_void_result */ - ) - { - engine_->run(setup(*st_, diag, params), ec); - } - - template - typename AlgoParams::result_type run_impl( - AlgoParams params, - error_code& ec, - diagnostics& diag, - std::false_type /* has_void_result */ - ) - { - engine_->run(setup(*st_, diag, params), ec); - return get_result(*st_); - } - - template - static void async_run_impl( - engine& eng, - connection_state& st, - AlgoParams params, - diagnostics& diag, - Handler&& handler, - std::true_type /* has_void_result */ - ) - { - eng.async_run(setup(st, diag, params), std::forward(handler)); - } - - template - static void async_run_impl( - engine& eng, - connection_state& st, - AlgoParams params, - diagnostics& diag, - Handler&& handler, - std::false_type /* has_void_result */ - ) - { - eng.async_run( - setup(st, diag, params), - make_intermediate_handler(generic_algo_fn{&st}, std::forward(handler)) - ); - } - - template - static void async_run_impl( - engine& eng, - connection_state& st, - AlgoParams params, - diagnostics& diag, - Handler&& handler - ) - { - async_run_impl(eng, st, params, diag, std::forward(handler), has_void_result{}); - } - - struct run_algo_initiation : initiation_base - { - using initiation_base::initiation_base; - - template - void operator()( - Handler&& handler, - diagnostics* diag, - engine* eng, - connection_state* st, - AlgoParams params - ) - { - async_run_impl(*eng, *st, params, *diag, std::forward(handler)); - } - }; - - // Connect - static connect_algo_params make_params_connect(const void* server_address, const handshake_params& params) - { - return connect_algo_params{server_address, params, false}; - } - - static connect_algo_params make_params_connect_v2(const connect_params& params) - { - return connect_algo_params{ - ¶ms.server_address, - make_hparams(params), - params.server_address.type() == address_type::unix_path - }; - } - - template - struct initiate_connect : initiation_base - { - using initiation_base::initiation_base; - - template - void operator()( - Handler&& handler, - diagnostics* diag, - engine* eng, - connection_state* st, - const EndpointType& endpoint, - handshake_params params - ) - { - async_run_impl( - *eng, - *st, - make_params_connect(&endpoint, params), - *diag, - std::forward(handler) - ); - } - }; - - struct initiate_connect_v2 : initiation_base - { - using initiation_base::initiation_base; - - template - void operator()( - Handler&& handler, - diagnostics* diag, - engine* eng, - connection_state* st, - const connect_params* params - ) - { - async_run_impl(*eng, *st, make_params_connect_v2(*params), *diag, std::forward(handler)); - } - }; - - // execute - struct initiate_execute : initiation_base - { - using initiation_base::initiation_base; - - template - void operator()( - Handler&& handler, - diagnostics* diag, - engine* eng, - connection_state* st, - ExecutionRequest&& req, - execution_processor* proc - ) - { - async_run_impl( - *eng, - *st, - execute_algo_params{make_request(std::forward(req), *st), proc}, - *diag, - std::forward(handler) - ); - } - }; - - // start execution - struct initiate_start_execution : initiation_base - { - using initiation_base::initiation_base; - - template - void operator()( - Handler&& handler, - diagnostics* diag, - engine* eng, - connection_state* st, - ExecutionRequest&& req, - execution_processor* proc - ) - { - async_run_impl( - *eng, - *st, - start_execution_algo_params{make_request(std::forward(req), *st), proc}, - *diag, - std::forward(handler) - ); - } - }; - -public: - BOOST_MYSQL_DECL connection_impl( - std::size_t read_buff_size, - std::size_t max_buffer_size, - std::unique_ptr eng - ); - - BOOST_MYSQL_DECL metadata_mode meta_mode() const; - BOOST_MYSQL_DECL void set_meta_mode(metadata_mode m); - BOOST_MYSQL_DECL bool ssl_active() const; - BOOST_MYSQL_DECL bool backslash_escapes() const; - BOOST_MYSQL_DECL system::result current_character_set() const; - BOOST_MYSQL_DECL boost::optional connection_id() const; - BOOST_MYSQL_DECL diagnostics& shared_diag(); - - engine& get_engine() - { - BOOST_ASSERT(engine_); - return *engine_; - } - - const engine& get_engine() const - { - BOOST_ASSERT(engine_); - return *engine_; - } - - // Generic algorithm - template - typename AlgoParams::result_type run(AlgoParams params, error_code& ec, diagnostics& diag) - { - return run_impl(params, ec, diag, has_void_result{}); - } - - template - auto async_run(AlgoParams params, diagnostics& diag, CompletionToken&& token) - -> decltype(asio::async_initiate>( - run_algo_initiation(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - params - )) - { - return asio::async_initiate>( - run_algo_initiation(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - params - ); - } - - // Connect - template - void connect( - const EndpointType& endpoint, - const handshake_params& params, - error_code& err, - diagnostics& diag - ) - { - run(make_params_connect(&endpoint, params), err, diag); - } - - void connect_v2(const connect_params& params, error_code& err, diagnostics& diag) - { - run(make_params_connect_v2(params), err, diag); - } - - template - auto async_connect( - const EndpointType& endpoint, - const handshake_params& params, - diagnostics& diag, - CompletionToken&& token - ) - -> decltype(asio::async_initiate( - initiate_connect(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - endpoint, - params - )) - { - return asio::async_initiate( - initiate_connect(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - endpoint, - params - ); - } - - template - auto async_connect_v2(const connect_params& params, diagnostics& diag, CompletionToken&& token) - -> decltype(asio::async_initiate( - initiate_connect_v2(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - ¶ms - )) - { - return asio::async_initiate( - initiate_connect_v2(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - ¶ms - ); - } - - // Handshake - handshake_algo_params make_params_handshake(const handshake_params& params) const - { - return {params, false}; - } - - // Execute - template - void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag) - { - run( - execute_algo_params{ - make_request(std::forward(req), *st_), - &access::get_impl(result).get_interface() - }, - err, - diag - ); - } - - template - auto async_execute( - ExecutionRequest&& req, - ResultsType& result, - diagnostics& diag, - CompletionToken&& token - ) - -> decltype(asio::async_initiate( - initiate_execute(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - std::forward(req), - &access::get_impl(result).get_interface() - )) - { - return asio::async_initiate( - initiate_execute(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - std::forward(req), - &access::get_impl(result).get_interface() - ); - } - - // Start execution - template - void start_execution( - ExecutionRequest&& req, - ExecutionStateType& exec_st, - error_code& err, - diagnostics& diag - ) - { - run( - start_execution_algo_params{ - make_request(std::forward(req), *st_), - &access::get_impl(exec_st).get_interface() - }, - err, - diag - ); - } - - template - auto async_start_execution( - ExecutionRequest&& req, - ExecutionStateType& exec_st, - diagnostics& diag, - CompletionToken&& token - ) - -> decltype(asio::async_initiate( - initiate_start_execution(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - std::forward(req), - &access::get_impl(exec_st).get_interface() - )) - { - return asio::async_initiate( - initiate_start_execution(get_executor()), - token, - &diag, - engine_.get(), - st_.get(), - std::forward(req), - &access::get_impl(exec_st).get_interface() - ); - } - - // Read some rows (dynamic) - read_some_rows_dynamic_algo_params make_params_read_some_rows(execution_state& st) const - { - return {&access::get_impl(st).get_interface()}; - } - - // Read some rows (static) - template - read_some_rows_algo_params make_params_read_some_rows_static( - ExecutionState& exec_st, - span output - ) const - { - return { - &access::get_impl(exec_st).get_interface(), - access::get_impl(exec_st).make_output_ref(output) - }; - } - - // Read resultset head - template - read_resultset_head_algo_params make_params_read_resultset_head(ExecutionStateType& st) const - { - return {&detail::access::get_impl(st).get_interface()}; - } - - // Close statement - close_statement_algo_params make_params_close_statement(statement stmt) const { return {stmt.id()}; } - - // Run pipeline. Separately compiled to avoid including the pipeline header here - BOOST_MYSQL_DECL - static run_pipeline_algo_params make_params_pipeline( - const pipeline_request& req, - std::vector& response - ); - - // Exposed for testing - connection_state& get_state() { return *st_; } -}; - -// To use some completion tokens, like deferred, in C++11, the old macros -// BOOST_ASIO_INITFN_AUTO_RESULT_TYPE are no longer enough. -// Helper typedefs to reduce duplication -template -using async_run_t = decltype(std::declval().async_run( - std::declval(), - std::declval(), - std::declval() -)); - -template -using async_connect_t = decltype(std::declval().async_connect( - std::declval(), - std::declval(), - std::declval(), - std::declval() -)); - -template -using async_connect_v2_t = decltype(std::declval().async_connect_v2( - std::declval(), - std::declval(), - std::declval() -)); - -template -using async_execute_t = decltype(std::declval().async_execute( - std::declval(), - std::declval(), - std::declval(), - std::declval() -)); - -template -using async_start_execution_t = decltype(std::declval().async_start_execution( - std::declval(), - std::declval(), - std::declval(), - std::declval() -)); - -template -using async_handshake_t = async_run_t; - -template -using async_read_resultset_head_t = async_run_t; - -template -using async_read_some_rows_dynamic_t = async_run_t; - -template -using async_prepare_statement_t = async_run_t; - -template -using async_close_statement_t = async_run_t; - -template -using async_set_character_set_t = async_run_t; - -template -using async_ping_t = async_run_t; - -template -using async_reset_connection_t = async_run_t; - -template -using async_quit_connection_t = async_run_t; - -template -using async_close_connection_t = async_run_t; - -template -using async_run_pipeline_t = async_run_t; - -} // namespace detail -} // namespace mysql -} // namespace boost - -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif - -#endif diff --git a/include/boost/mysql/detail/engine.hpp b/include/boost/mysql/detail/engine.hpp index 67c8f76d4..5fb3d0204 100644 --- a/include/boost/mysql/detail/engine.hpp +++ b/include/boost/mysql/detail/engine.hpp @@ -8,25 +8,99 @@ #ifndef BOOST_MYSQL_DETAIL_ENGINE_HPP #define BOOST_MYSQL_DETAIL_ENGINE_HPP +#include +#include + #include #include #include +#include +#include +#include +#include + +#include +#include namespace boost { namespace mysql { namespace detail { +class mysql_stream : public capy::any_stream +{ + bool supports_tls_; + +public: + explicit mysql_stream(bool supports_tls) : supports_tls_(supports_tls) {} + virtual ~mysql_stream() {} + virtual capy::io_task read_some(capy::mutable_buffer) = 0; + virtual capy::io_task write_some(capy::const_buffer) = 0; + virtual capy::io_task<> connect(const any_address&) = 0; + virtual capy::io_task<> tls_handshake() = 0; + virtual capy::io_task<> tls_shutdown() = 0; + virtual capy::io_task<> close() = 0; + + bool supports_tls() const { return supports_tls_; } +}; + class engine { + std::unique_ptr stream_; + public: - using executor_type = asio::any_io_executor; + engine(std::unique_ptr stream) noexcept : stream_(std::move(stream)) {} + ~engine() {} + capy::io_task<> run(any_resumable_ref resumable) + { + // Start the operation + auto act = resumable.resume(error_code(), 0u); - virtual ~engine() {} - virtual executor_type get_executor() = 0; - virtual bool supports_ssl() const = 0; - virtual void run(any_resumable_ref resumable, error_code& err) = 0; - virtual void async_run(any_resumable_ref resumable, asio::any_completion_handler) = 0; + while (true) + { + switch (act.type()) + { + case next_action_type::none: co_return {act.error()}; + case next_action_type::read: + { + auto [ec, n] = co_await stream_->read_some(capy::make_buffer(act.read_args().buffer)); + act = resumable.resume(ec, n); + break; + } + case next_action_type::write: + { + auto [ec, n] = co_await stream_->write_some(capy::make_buffer(act.write_args().buffer)); + act = resumable.resume(ec, n); + break; + } + case next_action_type::ssl_handshake: + { + auto [ec] = co_await stream_->tls_handshake(); + act = resumable.resume(ec, 0u); + break; + } + case next_action_type::ssl_shutdown: + { + auto [ec] = co_await stream_->tls_shutdown(); + act = resumable.resume(ec, 0u); + break; + } + case next_action_type::connect: + { + auto [ec] = co_await stream_->connect(act.connect_endpoint()); + act = resumable.resume(ec, 0u); + break; + } + case next_action_type::close: + { + auto [ec] = co_await stream_->close(); + act = resumable.resume(ec, 0u); + break; + } + default: BOOST_ASSERT(false); co_return {}; + } + } + } }; } // namespace detail diff --git a/include/boost/mysql/detail/engine_impl.hpp b/include/boost/mysql/detail/engine_impl.hpp deleted file mode 100644 index efe045aec..000000000 --- a/include/boost/mysql/detail/engine_impl.hpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// Copyright (c) 2019-2025 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_DETAIL_ENGINE_IMPL_HPP -#define BOOST_MYSQL_DETAIL_ENGINE_IMPL_HPP - -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace boost { -namespace mysql { -namespace detail { - -inline asio::mutable_buffer to_buffer(span buff) noexcept -{ - return asio::mutable_buffer(buff.data(), buff.size()); -} - -inline bool has_terminal_cancellation(asio::cancellation_type_t cancel_type) -{ - return static_cast(cancel_type & asio::cancellation_type_t::terminal); -} - -template -struct run_algo_op -{ - int resume_point_{0}; - EngineStream& stream_; - any_resumable_ref resumable_; - bool has_done_io_{false}; - error_code stored_ec_; - - run_algo_op(EngineStream& stream, any_resumable_ref algo) noexcept : stream_(stream), resumable_(algo) {} - - template - void operator()(Self& self, error_code io_ec = {}, std::size_t bytes_transferred = 0) - { - next_action act; - - switch (resume_point_) - { - case 0: - - while (true) - { - // If we were cancelled, but the last operation completed successfully, - // set a cancelled error code so the algorithm exits. This might happen - // if a cancellation signal is emitted after an intermediate operation succeeded - // but before the handler was called. - if (!io_ec && has_terminal_cancellation(self.cancelled())) - io_ec = asio::error::operation_aborted; - - // Run the op - act = resumable_.resume(io_ec, bytes_transferred); - if (act.is_done()) - { - stored_ec_ = act.error(); - if (!has_done_io_) - { - BOOST_MYSQL_YIELD( - resume_point_, - 1, - asio::async_immediate(stream_.get_executor(), std::move(self)) - ) - } - self.complete(stored_ec_); - return; - } - else if (act.type() == next_action_type::read) - { - BOOST_MYSQL_YIELD( - resume_point_, - 2, - stream_.async_read_some( - to_buffer(act.read_args().buffer), - act.read_args().use_ssl, - std::move(self) - ) - ) - has_done_io_ = true; - } - else if (act.type() == next_action_type::write) - { - BOOST_MYSQL_YIELD( - resume_point_, - 3, - stream_.async_write_some( - asio::buffer(act.write_args().buffer), - act.write_args().use_ssl, - std::move(self) - ) - ) - has_done_io_ = true; - } - else if (act.type() == next_action_type::ssl_handshake) - { - BOOST_MYSQL_YIELD(resume_point_, 4, stream_.async_ssl_handshake(std::move(self))) - has_done_io_ = true; - } - else if (act.type() == next_action_type::ssl_shutdown) - { - BOOST_MYSQL_YIELD(resume_point_, 5, stream_.async_ssl_shutdown(std::move(self))) - has_done_io_ = true; - } - else if (act.type() == next_action_type::connect) - { - BOOST_MYSQL_YIELD( - resume_point_, - 6, - stream_.async_connect(act.connect_endpoint(), std::move(self)) - ) - has_done_io_ = true; - } - else - { - BOOST_ASSERT(act.type() == next_action_type::close); - stream_.close(io_ec); - } - } - } - } -}; - -// EngineStream is an "extended" stream concept, with the following operations: -// using executor_type = asio::any_io_executor; -// executor_type get_executor(); -// bool supports_ssl() const; -// std::size_t read_some(asio::mutable_buffer, bool use_ssl, error_code&); -// void async_read_some(asio::mutable_buffer, bool use_ssl, CompletinToken&&); -// std::size_t write_some(asio::const_buffer, bool use_ssl, error_code&); -// void async_write_some(asio::const_buffer, bool use_ssl, CompletinToken&&); -// void ssl_handshake(error_code&); -// void async_ssl_handshake(CompletionToken&&); -// void ssl_shutdown(error_code&); -// void async_ssl_shutdown(CompletionToken&&); -// void connect(const void* server_address, error_code&); -// void async_connect(const void* server_address, CompletionToken&&); -// void close(error_code&); -// Async operations are only required to support callback types -// See stream_adaptor for an implementation -template -class engine_impl final : public engine -{ - EngineStream stream_; - -public: - template - engine_impl(Args&&... args) : stream_(std::forward(args)...) - { - } - - EngineStream& stream() { return stream_; } - const EngineStream& stream() const { return stream_; } - - using executor_type = asio::any_io_executor; - executor_type get_executor() override final { return stream_.get_executor(); } - - bool supports_ssl() const override final { return stream_.supports_ssl(); } - - void run(any_resumable_ref resumable, error_code& ec) override final - { - ec.clear(); - error_code io_ec; - std::size_t bytes_transferred = 0; - - while (true) - { - // Run the op - auto act = resumable.resume(io_ec, bytes_transferred); - - // Apply the next action - bytes_transferred = 0; - if (act.is_done()) - { - ec = act.error(); - return; - } - else if (act.type() == next_action_type::read) - { - bytes_transferred = stream_.read_some( - to_buffer(act.read_args().buffer), - act.read_args().use_ssl, - io_ec - ); - } - else if (act.type() == next_action_type::write) - { - bytes_transferred = stream_.write_some( - asio::buffer(act.write_args().buffer), - act.write_args().use_ssl, - io_ec - ); - } - else if (act.type() == next_action_type::ssl_handshake) - { - stream_.ssl_handshake(io_ec); - } - else if (act.type() == next_action_type::ssl_shutdown) - { - stream_.ssl_shutdown(io_ec); - } - else if (act.type() == next_action_type::connect) - { - stream_.connect(act.connect_endpoint(), io_ec); - } - else - { - BOOST_ASSERT(act.type() == next_action_type::close); - stream_.close(io_ec); - } - } - } - - void async_run(any_resumable_ref resumable, asio::any_completion_handler h) - override final - { - return asio::async_compose, void(error_code)>( - run_algo_op(stream_, resumable), - h, - stream_ - ); - } -}; - -} // namespace detail -} // namespace mysql -} // namespace boost - -#endif diff --git a/include/boost/mysql/detail/engine_stream_adaptor.hpp b/include/boost/mysql/detail/engine_stream_adaptor.hpp deleted file mode 100644 index 141324352..000000000 --- a/include/boost/mysql/detail/engine_stream_adaptor.hpp +++ /dev/null @@ -1,314 +0,0 @@ -// -// Copyright (c) 2019-2025 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_DETAIL_ENGINE_STREAM_ADAPTOR_HPP -#define BOOST_MYSQL_DETAIL_ENGINE_STREAM_ADAPTOR_HPP - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -// Adapts a regular Asio Stream to meet the EngineStream requirements -// We only use callbacks with the async functions in this file, so no need to support arbitrary return types - -namespace boost { -namespace mysql { -namespace detail { - -// Connect and close helpers -// LCOV_EXCL_START -template -void do_connect_impl(Stream&, const void*, error_code&, std::false_type) -{ - BOOST_ASSERT(false); -} -// LCOV_EXCL_STOP - -template -void do_connect_impl(Stream& stream, const void* ep, error_code& ec, std::true_type) -{ - stream.lowest_layer().connect( - *static_cast(ep), - ec - ); -} - -template -void do_connect(Stream& stream, const void* ep, error_code& ec) -{ - do_connect_impl(stream, ep, ec, is_socket_stream{}); -} - -// LCOV_EXCL_START -template -void do_async_connect_impl(Stream&, const void*, CompletionToken&&, std::false_type) -{ - BOOST_ASSERT(false); -} -// LCOV_EXCL_STOP - -template -void do_async_connect_impl(Stream& stream, const void* ep, CompletionToken&& token, std::true_type) -{ - stream.lowest_layer().async_connect( - *static_cast(ep), - std::forward(token) - ); -} - -template -void do_async_connect(Stream& stream, const void* ep, CompletionToken&& token) -{ - do_async_connect_impl(stream, ep, std::forward(token), is_socket_stream{}); -} - -// LCOV_EXCL_START -template -void do_close_impl(Stream&, error_code&, std::false_type) -{ - BOOST_ASSERT(false); -} -// LCOV_EXCL_STOP - -template -void do_close_impl(Stream& stream, error_code& ec, std::true_type) -{ - stream.lowest_layer().shutdown(asio::socket_base::shutdown_both, ec); - stream.lowest_layer().close(ec); -} - -template -void do_close(Stream& stream, error_code& ec) -{ - do_close_impl(stream, ec, is_socket_stream{}); -} - -template -class engine_stream_adaptor -{ - Stream stream_; - -public: - template - engine_stream_adaptor(Args&&... args) : stream_(std::forward(args)...) - { - } - - Stream& stream() { return stream_; } - const Stream& stream() const { return stream_; } - - bool supports_ssl() const { return false; } - - using executor_type = asio::any_io_executor; - executor_type get_executor() { return stream_.get_executor(); } - - // SSL - // LCOV_EXCL_START - void ssl_handshake(error_code&) { BOOST_ASSERT(false); } - - template - void async_ssl_handshake(CompletinToken&&) - { - BOOST_ASSERT(false); - } - - void ssl_shutdown(error_code&) { BOOST_ASSERT(false); } - - template - void async_ssl_shutdown(CompletionToken&&) - { - BOOST_ASSERT(false); - } - // LCOV_EXCL_STOP - - // Reading - std::size_t read_some(boost::asio::mutable_buffer buff, bool use_ssl, error_code& ec) - { - BOOST_ASSERT(!use_ssl); - boost::ignore_unused(use_ssl); - return stream_.read_some(buff, ec); - } - - template - void async_read_some(boost::asio::mutable_buffer buff, bool use_ssl, CompletionToken&& token) - { - BOOST_ASSERT(!use_ssl); - boost::ignore_unused(use_ssl); - stream_.async_read_some(buff, std::forward(token)); - } - - // Writing - std::size_t write_some(boost::asio::const_buffer buff, bool use_ssl, error_code& ec) - { - BOOST_ASSERT(!use_ssl); - boost::ignore_unused(use_ssl); - return stream_.write_some(buff, ec); - } - - template - void async_write_some(boost::asio::const_buffer buff, bool use_ssl, CompletionToken&& token) - { - BOOST_ASSERT(!use_ssl); - boost::ignore_unused(use_ssl); - stream_.async_write_some(buff, std::forward(token)); - } - - // Connect and close - void connect(const void* endpoint, error_code& ec) { do_connect(stream_, endpoint, ec); } - - template - void async_connect(const void* endpoint, CompletionToken&& token) - { - do_async_connect(stream_, endpoint, std::forward(token)); - } - - void close(error_code& ec) { do_close(stream_, ec); } -}; - -template -class engine_stream_adaptor> -{ - asio::ssl::stream stream_; - -public: - template - engine_stream_adaptor(Args&&... args) : stream_(std::forward(args)...) - { - } - - asio::ssl::stream& stream() { return stream_; } - const asio::ssl::stream& stream() const { return stream_; } - - bool supports_ssl() const { return true; } - - using executor_type = asio::any_io_executor; - executor_type get_executor() { return stream_.get_executor(); } - - // SSL - void ssl_handshake(error_code& ec) { stream_.handshake(asio::ssl::stream_base::client, ec); } - - template - void async_ssl_handshake(CompletionToken&& token) - { - stream_.async_handshake(asio::ssl::stream_base::client, std::forward(token)); - } - - void ssl_shutdown(error_code& ec) { stream_.shutdown(ec); } - - template - void async_ssl_shutdown(CompletionToken&& token) - { - stream_.async_shutdown(std::forward(token)); - } - - // Reading - std::size_t read_some(boost::asio::mutable_buffer buff, bool use_ssl, error_code& ec) - { - if (use_ssl) - { - return stream_.read_some(buff, ec); - } - else - { - return stream_.next_layer().read_some(buff, ec); - } - } - - template - void async_read_some(boost::asio::mutable_buffer buff, bool use_ssl, CompletionToken&& token) - { - if (use_ssl) - { - stream_.async_read_some(buff, std::forward(token)); - } - else - { - stream_.next_layer().async_read_some(buff, std::forward(token)); - } - } - - // Writing - std::size_t write_some(boost::asio::const_buffer buff, bool use_ssl, error_code& ec) - { - if (use_ssl) - { - return stream_.write_some(buff, ec); - } - else - { - return stream_.next_layer().write_some(buff, ec); - } - } - - template - void async_write_some(boost::asio::const_buffer buff, bool use_ssl, CompletionToken&& token) - { - if (use_ssl) - { - stream_.async_write_some(buff, std::forward(token)); - } - else - { - stream_.next_layer().async_write_some(buff, std::forward(token)); - } - } - - // Connect and close - void connect(const void* endpoint, error_code& ec) { do_connect(stream_, endpoint, ec); } - - template - void async_connect(const void* endpoint, CompletionToken&& token) - { - do_async_connect(stream_, endpoint, std::forward(token)); - } - - void close(error_code& ec) { do_close(stream_, ec); } -}; - -#ifdef BOOST_MYSQL_SEPARATE_COMPILATION -extern template class engine_impl>>; -extern template class engine_impl>; -#endif - -template -std::unique_ptr make_engine(Args&&... args) -{ - return std::unique_ptr(new engine_impl>(std::forward(args)...) - ); -} - -// Use these only for engines created using make_engine -template -Stream& stream_from_engine(engine& eng) -{ - using derived_t = engine_impl>; - return static_cast(eng).stream().stream(); -} - -template -const Stream& stream_from_engine(const engine& eng) -{ - using derived_t = engine_impl>; - return static_cast(eng).stream().stream(); -} - -} // namespace detail -} // namespace mysql -} // namespace boost - -#endif diff --git a/include/boost/mysql/detail/escape_string.hpp b/include/boost/mysql/detail/escape_string.hpp index 5d77385d0..fe5946498 100644 --- a/include/boost/mysql/detail/escape_string.hpp +++ b/include/boost/mysql/detail/escape_string.hpp @@ -9,13 +9,14 @@ #define BOOST_MYSQL_DETAIL_ESCAPE_STRING_HPP #include -#include #include #include #include +#include + namespace boost { namespace mysql { @@ -25,14 +26,11 @@ struct format_options; namespace detail { BOOST_ATTRIBUTE_NODISCARD BOOST_MYSQL_DECL error_code -escape_string(string_view input, const format_options& opts, char quote_char, output_string_ref output); +escape_string(std::string_view input, const format_options& opts, char quote_char, output_string_ref output); } // namespace detail } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/execution_concepts.hpp b/include/boost/mysql/detail/execution_concepts.hpp index 9c859ba94..9ed5e07f6 100644 --- a/include/boost/mysql/detail/execution_concepts.hpp +++ b/include/boost/mysql/detail/execution_concepts.hpp @@ -8,11 +8,10 @@ #ifndef BOOST_MYSQL_DETAIL_EXECUTION_CONCEPTS_HPP #define BOOST_MYSQL_DETAIL_EXECUTION_CONCEPTS_HPP -#include - #include #include +#include #include #ifdef BOOST_MYSQL_HAS_CONCEPTS diff --git a/include/boost/mysql/detail/execution_processor/execution_processor.hpp b/include/boost/mysql/detail/execution_processor/execution_processor.hpp index 2aab43e90..cb79e9b1c 100644 --- a/include/boost/mysql/detail/execution_processor/execution_processor.hpp +++ b/include/boost/mysql/detail/execution_processor/execution_processor.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -22,11 +21,12 @@ #include #include -#include #include #include #include +#include +#include namespace boost { namespace mysql { @@ -51,7 +51,7 @@ class output_ref constexpr output_ref() noexcept = default; template - constexpr output_ref(boost::span span, std::size_t type_index, std::size_t offset = 0) noexcept + constexpr output_ref(std::span span, std::size_t type_index, std::size_t offset = 0) noexcept : data_(span.data()), max_size_(span.size()), type_index_(type_index), offset_(offset) { } @@ -121,7 +121,11 @@ class execution_processor void on_row_batch_finish() { on_row_batch_finish_impl(); } BOOST_ATTRIBUTE_NODISCARD - error_code on_row(span msg, const output_ref& ref, std::vector& storage) + error_code on_row( + std::span msg, + const output_ref& ref, + std::vector& storage + ) { BOOST_ASSERT(is_reading_rows()); return on_row_impl(msg, ref, storage); @@ -157,7 +161,7 @@ class execution_processor virtual error_code on_meta_impl(const coldef_view& coldef, bool is_last, diagnostics& diag) = 0; virtual error_code on_row_ok_packet_impl(const ok_view& pack) = 0; virtual error_code on_row_impl( - span msg, + std::span msg, const output_ref& ref, std::vector& storage ) = 0; diff --git a/include/boost/mysql/detail/execution_processor/execution_state_impl.hpp b/include/boost/mysql/detail/execution_processor/execution_state_impl.hpp index 9e45902d6..7fc410889 100644 --- a/include/boost/mysql/detail/execution_processor/execution_state_impl.hpp +++ b/include/boost/mysql/detail/execution_processor/execution_state_impl.hpp @@ -13,13 +13,13 @@ #include #include #include -#include #include #include #include +#include #include namespace boost { @@ -64,8 +64,11 @@ class execution_state_impl final : public execution_processor error_code on_meta_impl(const coldef_view&, bool, diagnostics&) override final; BOOST_MYSQL_DECL - error_code on_row_impl(span msg, const output_ref&, std::vector& fields) - override final; + error_code on_row_impl( + std::span msg, + const output_ref&, + std::vector& fields + ) override final; BOOST_MYSQL_DECL error_code on_row_ok_packet_impl(const ok_view& pack) override final; @@ -97,10 +100,10 @@ class execution_state_impl final : public execution_processor return eof_data_.warnings; } - string_view get_info() const noexcept + std::string_view get_info() const noexcept { BOOST_ASSERT(eof_data_.has_value); - return string_view(info_.data(), info_.size()); + return std::string_view(info_.data(), info_.size()); } bool get_is_out_params() const noexcept @@ -116,8 +119,5 @@ class execution_state_impl final : public execution_processor } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/execution_processor/results_impl.hpp b/include/boost/mysql/detail/execution_processor/results_impl.hpp index cd98dc08f..1555c3b94 100644 --- a/include/boost/mysql/detail/execution_processor/results_impl.hpp +++ b/include/boost/mysql/detail/execution_processor/results_impl.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -22,6 +21,8 @@ #include +#include + namespace boost { namespace mysql { namespace detail { @@ -126,10 +127,10 @@ class results_impl final : public execution_processor unsigned get_warning_count(std::size_t index) const noexcept { return get_resultset(index).warnings; } - string_view get_info(std::size_t index) const noexcept + std::string_view get_info(std::size_t index) const noexcept { const auto& resultset_data = get_resultset(index); - return string_view(info_.data() + resultset_data.info_offset, resultset_data.info_size); + return std::string_view(info_.data() + resultset_data.info_offset, resultset_data.info_size); } bool get_is_out_params(std::size_t index) const noexcept { return get_resultset(index).is_out_params; } @@ -151,8 +152,11 @@ class results_impl final : public execution_processor error_code on_meta_impl(const coldef_view&, bool, diagnostics&) override final; BOOST_MYSQL_DECL - error_code on_row_impl(span msg, const output_ref&, std::vector&) - override final; + error_code on_row_impl( + std::span msg, + const output_ref&, + std::vector& + ) override final; BOOST_MYSQL_DECL error_code on_row_ok_packet_impl(const ok_view& pack) override final; @@ -212,8 +216,5 @@ class results_impl final : public execution_processor } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/execution_processor/static_execution_state_impl.hpp b/include/boost/mysql/detail/execution_processor/static_execution_state_impl.hpp index a80243b7d..90c61e510 100644 --- a/include/boost/mysql/detail/execution_processor/static_execution_state_impl.hpp +++ b/include/boost/mysql/detail/execution_processor/static_execution_state_impl.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -26,14 +25,18 @@ #include #include +#include #include namespace boost { namespace mysql { namespace detail { -using execst_parse_fn_t = - error_code (*)(span pos_map, span from, const output_ref& ref); +using execst_parse_fn_t = error_code (*)( + std::span pos_map, + std::span from, + const output_ref& ref +); struct execst_resultset_descriptor { @@ -52,7 +55,7 @@ class execst_external_data std::size_t* pos_map; }; - execst_external_data(span desc, ptr_data ptr) noexcept + execst_external_data(std::span desc, ptr_data ptr) noexcept : desc_(desc), ptr_(ptr) { } @@ -83,15 +86,15 @@ class execst_external_data BOOST_ASSERT(idx < num_resultsets()); return desc_[idx].type_index; } - span pos_map(std::size_t idx) const noexcept + std::span pos_map(std::size_t idx) const noexcept { - return span(ptr_.pos_map, num_columns(idx)); + return std::span(ptr_.pos_map, num_columns(idx)); } void set_pointers(ptr_data ptr) noexcept { ptr_ = ptr; } private: - span desc_; + std::span desc_; ptr_data ptr_; }; @@ -122,10 +125,10 @@ class static_execution_state_erased_impl final : public execution_processor return ok_data_.warnings; } - string_view get_info() const noexcept + std::string_view get_info() const noexcept { BOOST_ASSERT(ok_data_.has_value); - return string_view(info_.data(), info_.size()); + return std::string_view(info_.data(), info_.size()); } bool get_is_out_params() const noexcept @@ -166,7 +169,7 @@ class static_execution_state_erased_impl final : public execution_processor BOOST_MYSQL_DECL error_code on_row_impl( - span msg, + std::span msg, const output_ref& ref, std::vector& fields ) override final; @@ -180,8 +183,11 @@ class static_execution_state_erased_impl final : public execution_processor // Auxiliar name_table_t current_name_table() const noexcept { return ext_.name_table(resultset_index_ - 1); } - span current_pos_map() noexcept { return ext_.pos_map(resultset_index_ - 1); } - span current_pos_map() const noexcept { return ext_.pos_map(resultset_index_ - 1); } + std::span current_pos_map() noexcept { return ext_.pos_map(resultset_index_ - 1); } + std::span current_pos_map() const noexcept + { + return ext_.pos_map(resultset_index_ - 1); + } error_code meta_check(diagnostics& diag) const { @@ -197,8 +203,8 @@ class static_execution_state_erased_impl final : public execution_processor template static error_code execst_parse_fn( - span pos_map, - span from, + std::span pos_map, + std::span from, const output_ref& ref ) { @@ -278,7 +284,7 @@ class static_execution_state_impl ~static_execution_state_impl() = default; template - output_ref make_output_ref(span output, std::size_t offset = 0) const noexcept + output_ref make_output_ref(std::span output, std::size_t offset = 0) const noexcept { constexpr std::size_t index = get_type_index(); static_assert( @@ -296,9 +302,6 @@ class static_execution_state_impl } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif // BOOST_MYSQL_CXX14 diff --git a/include/boost/mysql/detail/execution_processor/static_results_impl.hpp b/include/boost/mysql/detail/execution_processor/static_results_impl.hpp index 32af3d46e..58ee2e0fe 100644 --- a/include/boost/mysql/detail/execution_processor/static_results_impl.hpp +++ b/include/boost/mysql/detail/execution_processor/static_results_impl.hpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -28,6 +27,7 @@ #include #include +#include namespace boost { namespace mysql { @@ -35,7 +35,7 @@ namespace detail { using results_reset_fn_t = void (*)(void*); using results_parse_fn_t = - error_code (*)(span pos_map, span from, void* to); + error_code (*)(std::span pos_map, std::span from, void* to); struct results_resultset_descriptor { @@ -69,7 +69,7 @@ class results_external_data }; results_external_data( - span desc, + std::span desc, results_reset_fn_t reset, ptr_data ptr ) noexcept @@ -102,9 +102,9 @@ class results_external_data } results_reset_fn_t reset_fn() const noexcept { return reset_; } void* rows() const noexcept { return ptr_.rows; } - span pos_map(std::size_t idx) const noexcept + std::span pos_map(std::size_t idx) const noexcept { - return span(ptr_.pos_map, num_columns(idx)); + return std::span(ptr_.pos_map, num_columns(idx)); } static_per_resultset_data& per_result(std::size_t idx) const noexcept { @@ -113,7 +113,7 @@ class results_external_data } private: - span desc_; + std::span desc_; results_reset_fn_t reset_; ptr_data ptr_; }; @@ -143,10 +143,10 @@ class static_results_erased_impl final : public execution_processor unsigned get_warning_count(std::size_t index) const noexcept { return ext_.per_result(index).warnings; } - string_view get_info(std::size_t index) const noexcept + std::string_view get_info(std::size_t index) const noexcept { const auto& resultset_data = ext_.per_result(index); - return string_view(info_.data() + resultset_data.info_offset, resultset_data.info_size); + return std::string_view(info_.data() + resultset_data.info_offset, resultset_data.info_size); } bool get_is_out_params(std::size_t index) const noexcept { return ext_.per_result(index).is_out_params; } @@ -166,8 +166,11 @@ class static_results_erased_impl final : public execution_processor error_code on_meta_impl(const coldef_view& coldef, bool is_last, diagnostics& diag) override final; BOOST_MYSQL_DECL - error_code on_row_impl(span msg, const output_ref&, std::vector& fields) - override final; + error_code on_row_impl( + std::span msg, + const output_ref&, + std::vector& fields + ) override final; BOOST_MYSQL_DECL error_code on_row_ok_packet_impl(const ok_view& pack) override final; @@ -182,8 +185,11 @@ class static_results_erased_impl final : public execution_processor std::size_t resultset_index_{0}; // Helpers - span current_pos_map() noexcept { return ext_.pos_map(resultset_index_ - 1); } - span current_pos_map() const noexcept { return ext_.pos_map(resultset_index_ - 1); } + std::span current_pos_map() noexcept { return ext_.pos_map(resultset_index_ - 1); } + std::span current_pos_map() const noexcept + { + return ext_.pos_map(resultset_index_ - 1); + } name_table_t current_name_table() const noexcept { return ext_.name_table(resultset_index_ - 1); } static_per_resultset_data& current_resultset() noexcept { return ext_.per_result(resultset_index_ - 1); } metadata_collection_view current_resultset_meta() const noexcept @@ -229,7 +235,11 @@ struct results_fns } template - static error_code do_parse(span pos_map, span from, void* to) + static error_code do_parse( + std::span pos_map, + std::span from, + void* to + ) { using StaticRowT = mp11::mp_at_c, I>; auto& v = std::get(*static_cast(to)); @@ -250,8 +260,9 @@ struct results_fns } template - static constexpr std::array create_descriptors(mp11::index_sequence< - I...>) + static constexpr std::array create_descriptors( + mp11::index_sequence + ) { return {{create_descriptor()...}}; } @@ -264,7 +275,7 @@ BOOST_INLINE_CONSTEXPR std::array -using rows_span_t = boost::span< +using rows_span_t = std::span< const typename std::tuple_element...>>::type>; template @@ -344,9 +355,6 @@ class static_results_impl } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif // BOOST_MYSQL_CXX14 diff --git a/include/boost/mysql/detail/format_sql.hpp b/include/boost/mysql/detail/format_sql.hpp index b9bfa3984..91712230e 100644 --- a/include/boost/mysql/detail/format_sql.hpp +++ b/include/boost/mysql/detail/format_sql.hpp @@ -10,11 +10,12 @@ #include #include -#include #include #include +#include +#include #include #include @@ -149,7 +150,11 @@ template formattable_ref_impl make_formattable_ref(T&& v); BOOST_MYSQL_DECL -void vformat_sql_to(format_context_base& ctx, constant_string_view format_str, span args); +void vformat_sql_to( + format_context_base& ctx, + constant_string_view format_str, + std::span args +); } // namespace detail } // namespace mysql diff --git a/include/boost/mysql/detail/next_action.hpp b/include/boost/mysql/detail/next_action.hpp index fb214111e..6c246c383 100644 --- a/include/boost/mysql/detail/next_action.hpp +++ b/include/boost/mysql/detail/next_action.hpp @@ -8,12 +8,14 @@ #ifndef BOOST_MYSQL_DETAIL_NEXT_ACTION_HPP #define BOOST_MYSQL_DETAIL_NEXT_ACTION_HPP +#include #include #include -#include +#include #include +#include namespace boost { namespace mysql { @@ -35,13 +37,13 @@ class next_action public: struct read_args_t { - span buffer; + std::span buffer; bool use_ssl; }; struct write_args_t { - span buffer; + std::span buffer; bool use_ssl; }; @@ -58,7 +60,7 @@ class next_action BOOST_ASSERT(is_done()); return data_.ec; } - const void* connect_endpoint() const noexcept { return data_.connect_endpoint; } + const any_address& connect_endpoint() const noexcept { return *data_.connect_endpoint; } read_args_t read_args() const noexcept { BOOST_ASSERT(type_ == next_action_type::read); @@ -70,7 +72,7 @@ class next_action return data_.write_args; } - static next_action connect(const void* endpoint) noexcept + static next_action connect(const any_address* endpoint) noexcept { return next_action(next_action_type::connect, endpoint); } @@ -94,12 +96,12 @@ class next_action union data_t { error_code ec; - const void* connect_endpoint; + const any_address* connect_endpoint; read_args_t read_args; write_args_t write_args; data_t() noexcept : ec(error_code()) {} - data_t(const void* endpoint) noexcept : connect_endpoint(endpoint) {} + data_t(const any_address* endpoint) noexcept : connect_endpoint(endpoint) {} data_t(error_code ec) noexcept : ec(ec) {} data_t(read_args_t args) noexcept : read_args(args) {} data_t(write_args_t args) noexcept : write_args(args) {} diff --git a/include/boost/mysql/detail/ok_view.hpp b/include/boost/mysql/detail/ok_view.hpp index b97c1ca23..8b48fe634 100644 --- a/include/boost/mysql/detail/ok_view.hpp +++ b/include/boost/mysql/detail/ok_view.hpp @@ -8,11 +8,10 @@ #ifndef BOOST_MYSQL_DETAIL_OK_VIEW_HPP #define BOOST_MYSQL_DETAIL_OK_VIEW_HPP -#include - #include #include +#include namespace boost { namespace mysql { @@ -24,7 +23,7 @@ struct ok_view std::uint64_t last_insert_id; std::uint16_t status_flags; std::uint16_t warnings; - string_view info; + std::string_view info; bool more_results() const noexcept { return status_flags & status_flags::more_results; } bool backslash_escapes() const noexcept { return !(status_flags & status_flags::no_backslash_escapes); } diff --git a/include/boost/mysql/detail/output_string.hpp b/include/boost/mysql/detail/output_string.hpp index b9d675bf0..e15d1adf9 100644 --- a/include/boost/mysql/detail/output_string.hpp +++ b/include/boost/mysql/detail/output_string.hpp @@ -8,11 +8,10 @@ #ifndef BOOST_MYSQL_DETAIL_OUTPUT_STRING_HPP #define BOOST_MYSQL_DETAIL_OUTPUT_STRING_HPP -#include - #include #include +#include #ifdef BOOST_MYSQL_HAS_CONCEPTS #include @@ -63,7 +62,7 @@ class output_string_ref return output_string_ref(&do_append, &obj); } - void append(string_view data) + void append(std::string_view data) { if (data.size() > 0u) append_fn_(container_, data.data(), data.size()); diff --git a/include/boost/mysql/detail/row_impl.hpp b/include/boost/mysql/detail/row_impl.hpp index ab1a8eb52..d48ad7a12 100644 --- a/include/boost/mysql/detail/row_impl.hpp +++ b/include/boost/mysql/detail/row_impl.hpp @@ -12,7 +12,7 @@ #include -#include +#include #include #include @@ -23,11 +23,11 @@ namespace detail { // Adds num_fields default-constructed fields to the vector, return pointer to the first // allocated value. Used to allocate fields before deserialization -inline span add_fields(std::vector& storage, std::size_t num_fields) +inline std::span add_fields(std::vector& storage, std::size_t num_fields) { std::size_t old_size = storage.size(); storage.resize(old_size + num_fields); - return span(storage.data() + old_size, num_fields); + return std::span(storage.data() + old_size, num_fields); } // A field_view vector with strings pointing into a @@ -58,7 +58,7 @@ class row_impl void assign(const field_view* fields, std::size_t size); // Adds new default constructed fields to provide storage to deserialization - span add_fields(std::size_t num_fields) + std::span add_fields(std::size_t num_fields) { return ::boost::mysql::detail::add_fields(fields_, num_fields); } @@ -88,8 +88,5 @@ class row_impl } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/string_view_offset.hpp b/include/boost/mysql/detail/string_view_offset.hpp index b84d6b148..f7a81156e 100644 --- a/include/boost/mysql/detail/string_view_offset.hpp +++ b/include/boost/mysql/detail/string_view_offset.hpp @@ -14,7 +14,7 @@ namespace boost { namespace mysql { namespace detail { -// Represents a string_view using offsets into a buffer. +// Represents a std::string_view using offsets into a buffer. // Useful during deserialization, for buffers that may reallocate. struct string_view_offset { diff --git a/include/boost/mysql/detail/typing/meta_check_context.hpp b/include/boost/mysql/detail/typing/meta_check_context.hpp index 880bd9b6c..00e37276b 100644 --- a/include/boost/mysql/detail/typing/meta_check_context.hpp +++ b/include/boost/mysql/detail/typing/meta_check_context.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -22,6 +21,7 @@ #include #include +#include namespace boost { namespace mysql { @@ -63,7 +63,7 @@ class meta_check_context { std::unique_ptr errors_; std::size_t current_index_{}; - span pos_map_; + std::span pos_map_; name_table_t name_table_; metadata_collection_view meta_{}; bool nullability_checked_{}; @@ -87,7 +87,7 @@ class meta_check_context public: meta_check_context( - span pos_map, + std::span pos_map, name_table_t name_table, metadata_collection_view meta ) noexcept @@ -128,8 +128,5 @@ class meta_check_context } // namespace mysql } // namespace boost -#ifdef BOOST_MYSQL_HEADER_ONLY -#include -#endif #endif diff --git a/include/boost/mysql/detail/typing/pos_map.hpp b/include/boost/mysql/detail/typing/pos_map.hpp index 8fcb3702c..ccdaa7e50 100644 --- a/include/boost/mysql/detail/typing/pos_map.hpp +++ b/include/boost/mysql/detail/typing/pos_map.hpp @@ -11,13 +11,13 @@ #include #include #include -#include #include #include -#include #include +#include +#include namespace boost { namespace mysql { @@ -26,21 +26,21 @@ namespace detail { // These functions map C++ type positions to positions to positions in the DB query BOOST_INLINE_CONSTEXPR std::size_t pos_absent = static_cast(-1); -using name_table_t = boost::span; +using name_table_t = std::span; inline bool has_field_names(name_table_t name_table) noexcept { return !name_table.empty(); } -inline void pos_map_reset(span self) noexcept +inline void pos_map_reset(std::span self) noexcept { for (std::size_t i = 0; i < self.size(); ++i) self.data()[i] = pos_absent; } inline void pos_map_add_field( - span self, + std::span self, name_table_t name_table, std::size_t db_index, - string_view field_name + std::string_view field_name ) noexcept { if (has_field_names(name_table)) @@ -67,9 +67,9 @@ inline void pos_map_add_field( } inline field_view map_field_view( - span self, + std::span self, std::size_t cpp_index, - span array + std::span array ) noexcept { BOOST_ASSERT(cpp_index < self.size()); @@ -77,7 +77,7 @@ inline field_view map_field_view( } inline const metadata& map_metadata( - span self, + std::span self, std::size_t cpp_index, metadata_collection_view meta ) noexcept diff --git a/include/boost/mysql/detail/typing/readable_field_traits.hpp b/include/boost/mysql/detail/typing/readable_field_traits.hpp index dc2467028..4df6ccb9d 100644 --- a/include/boost/mysql/detail/typing/readable_field_traits.hpp +++ b/include/boost/mysql/detail/typing/readable_field_traits.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include namespace boost { diff --git a/include/boost/mysql/detail/typing/row_traits.hpp b/include/boost/mysql/detail/typing/row_traits.hpp index 232ecd238..6a7cb2d05 100644 --- a/include/boost/mysql/detail/typing/row_traits.hpp +++ b/include/boost/mysql/detail/typing/row_traits.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -32,6 +31,7 @@ #include #include +#include #include #include #include @@ -75,7 +75,7 @@ struct array_wrapper { T data_[N]; - constexpr boost::span span() const noexcept { return boost::span(data_); } + constexpr std::span span() const noexcept { return std::span(data_); } }; template @@ -85,7 +85,7 @@ struct array_wrapper { } data_; // allow empty brace initialization - constexpr boost::span span() const noexcept { return boost::span(); } + constexpr std::span span() const noexcept { return std::span(); } }; // Workaround for char_traits::length not being constexpr in C++14 @@ -103,10 +103,11 @@ using row_members = describe:: describe_members; template