...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
any_connection
is a type-erased alternative to connection
.
It's easier to use and features more functionality than plain connection
.
Note | |
---|---|
This feature is experimental. Its API may change in subsequent releases. |
When compared to connection
,
any_connection
:
connection
.
connection
can't make this
guarantee, especially when using TLS.
Stream
type. Doing this allows supporting the point above.
connection
.
any_connection
is expected
to replace connection
in the
long run.
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); }
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.
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 }