Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

(Experimental) Type-erased connections with any_connection

any_connection is a type-erased alternative to connection. It's easier to use and features more functionality than plain connection.

[Note] Note

This feature is experimental. Its API may change in subsequent releases.

When compared to connection, any_connection:

any_connection is expected to replace connection in the long run.

Example

To connect to a server using TCP, use the following:

void create_and_connect(
    string_view server_hostname,
    string_view username,
    string_view password,
    string_view database
)
{
    // connect_params contains all the info required to establish a session
    boost::mysql::connect_params params;
    params.server_address.emplace_host_and_port(server_hostname);  // server host
    params.username = username;                                    // username to log in as
    params.password = password;                                    // password to use
    params.database = database;                                    // database to use

    // The execution context, required to run I/O operations.
    boost::asio::io_context ctx;

    // A connection to the server. Note how the type doesn't depend
    // on the transport being used.
    boost::mysql::any_connection conn(ctx);

    // Connect to the server. This will perform hostname resolution,
    // TCP-level connect, and the MySQL handshake. After this function
    // succeeds, your connection is ready to run queries
    conn.connect(params);
}

connect_params::server_address is an any_address, which is a variant-like type that can hold a (hostname, port) pair or a UNIX socket path. For example, to connect using a UNIX socket:

void create_and_connect_unix(string_view username, string_view password, string_view database)
{
    // server_address may contain a UNIX socket path, too
    boost::mysql::connect_params params;
    params.server_address.emplace_unix_path("/var/run/mysqld/mysqld.sock");
    params.username = username;  // username to log in as
    params.password = password;  // password to use
    params.database = database;  // database to use

    // The execution context, required to run I/O operations.
    boost::asio::io_context ctx;

    // A connection to the server. Note how the type doesn't depend
    // on the transport being used.
    boost::mysql::any_connection conn(ctx);

    // Connect to the server. This will perform the
    // UNIX socket connect and the MySQL handshake. After this function
    // succeeds, your connection is ready to run queries
    conn.connect(params);
}

Reconnection

any_connection can always be reconnected. any_connection::connect and any_connection::async_connect will wipe any previous connection state. This works even if an error or a timeout occurred, as opposed to connection.

For instance, the following can be used to implement retries for connection establishment:

error_code connect_with_retries(
    boost::mysql::any_connection& conn,
    const boost::mysql::connect_params& params
)
{
    // We will be using the non-throwing overloads
    error_code ec;
    diagnostics diag;

    // Try to connect at most 10 times
    for (int i = 0; i < 10; ++i)
    {
        // Try to connect
        conn.connect(params, ec, diag);

        // If we succeeded, we're done
        if (!ec)
            return error_code();

        // Whoops, connect failed. We can sleep and try again
        std::cerr << "Failed connecting to MySQL: " << ec << ": " << diag.server_message() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    // No luck, retries expired
    return ec;
}

Likewise, if you encounter a fatal error (like a network error), just call connect or async_connect.

If you need reliable, long-lived connections, consider using a connection pool instead of rolling out your own strategy.

TLS

By default, any_connection uses TLS when using TCP connections and the server supports it. You can change this setting using connect_params::ssl:

// Don't ever use TLS, even if the server supports it
params.ssl = boost::mysql::ssl_mode::disable;

// ...

// Force using TLS. If the server doesn't support it, reject the connection
params.ssl = boost::mysql::ssl_mode::require;

See this section for more info on MySQL TLS negotiation.

By default, any_connection will create an boost::asio::ssl::context object with suitable default options for you, if required. If you want to configure TLS options beyond defaults, you can pass your own context to any_connection's constructor, and it will be used:

// The I/O context required to run network operations
boost::asio::io_context ctx;

// Create a SSL context
boost::asio::ssl::context ssl_ctx(boost::asio::ssl::context::tlsv12_client);

// Set options on the SSL context. Load the default certificate authorities
// and enable certificate verification. connect will fail if the server certificate
// isn't signed by a trusted entity or its hostname isn't "mysql"
ssl_ctx.set_default_verify_paths();
ssl_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
ssl_ctx.set_verify_callback(boost::asio::ssl::host_name_verification("mysql"));

// Construct an any_connection object passing the SSL context.
// You must keep ssl_ctx alive while using the connection.
boost::mysql::any_connection_params ctor_params;
ctor_params.ssl_context = &ssl_ctx;
boost::mysql::any_connection conn(ctx, ctor_params);

// Connect params
boost::mysql::connect_params params;
params.server_address.emplace_host_and_port(server_hostname);  // server host
params.username = mysql_username;                              // username to log in as
params.password = mysql_password;                              // password to use
params.ssl = boost::mysql::ssl_mode::require;                  // fail if TLS is not available

// Connect
error_code ec;
diagnostics diag;
conn.connect(params, ec, diag);
if (ec)
{
    // Handle error
}

PrevUpHomeNext