Skip to content

Commit 8fccb7e

Browse files
anarthallouistatta
authored andcommitted
Ruben Q4 update
1 parent d97f3bd commit 8fccb7e

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
---
2+
layout: post
3+
nav-class: dark
4+
categories: ruben
5+
title: "Boost.MySQL 1.87 and the new Boost citizens"
6+
author-id: ruben
7+
author-name: Rubén Pérez Hidalgo
8+
---
9+
10+
## Boost.MySQL 1.87
11+
12+
I already anticipated in [my previous post](https://cppalliance.org/ruben/2024/10/20/Ruben2024Q3Update.html)
13+
that Boost 1.87 was going to be an exciting release for the users of Boost.MySQL.
14+
Many new features have been promoted to stable, making using the library much more enjoyable.
15+
After putting the final touches during this last month, Boost 1.87 was released on December
16+
the 12th with all these new features.
17+
18+
Many of these changes make frequent tasks much easier. In this post, we will review some of the recommendations
19+
that changed in this release. We suggest sticking to these for new code. Old code will keep working as expected.
20+
21+
### Type-erased connections
22+
23+
[`any_connection`](https://www.boost.org/doc/libs/master/libs/mysql/doc/html/mysql/ref/boost__mysql__any_connection.html)
24+
is the new recommended way to open connections to MySQL. It features simpler connection establishment semantics,
25+
more functionality and lower compile times with no loss of performance. We recommend using it over
26+
`tcp_ssl_connection` and friends in new code. Since an example is worth a thousand words, here's one:
27+
28+
```cpp
29+
// Boost 1.86
30+
int main()
31+
{
32+
// The execution context, required for all I/O operations
33+
asio::io_context ctx;
34+
35+
// The SSL context, required for connections that use TLS.
36+
asio::ssl::context ssl_ctx(asio::ssl::context::tlsv12_client);
37+
38+
// Construct the connection
39+
mysql::tcp_ssl_connection conn(ctx, ssl_ctx);
40+
41+
// Resolve the hostname to get a collection of endpoints
42+
auto endpoints = resolver.resolve("localhost", mysql::default_port_string);
43+
44+
// Parameters specifying how to perform the MySQL handshake operation.
45+
mysql::handshake_params params(
46+
"some_username",
47+
"some_password",
48+
"some_database"
49+
);
50+
51+
// Connect to the server using the first endpoint returned by the resolver
52+
conn.connect(*endpoints.begin(), params);
53+
}
54+
55+
// Boost 1.87
56+
int main()
57+
{
58+
// The execution context, required to run I/O operations.
59+
asio::io_context ctx;
60+
61+
// Represents a connection to the MySQL server.
62+
mysql::any_connection conn(ctx);
63+
64+
// The hostname, username and password to use
65+
mysql::connect_params params {
66+
.server_address = mysql::host_and_port("some_host"),
67+
.username = "some_username",
68+
.password = "some_password",
69+
.database = "some_database",
70+
};
71+
72+
// Connect to the server
73+
conn.connect(params);
74+
}
75+
```
76+
77+
### Client-side SQL formatting and with_params
78+
79+
`with_params` can be used instead of prepared statements for one-off queries:
80+
81+
```cpp
82+
// Boost 1.86
83+
void lookup(mysql::tcp_ssl_connection& conn, int id)
84+
{
85+
// Prepare a statement
86+
mysql::statement stmt = conn.prepare_statement("SELECT * FROM user WHERE id = ?");
87+
88+
// Execute it
89+
mysql::static_results<user> res;
90+
conn.execute(stmt.bind(id), res);
91+
92+
// Close it
93+
conn.close_statement(stmt);
94+
95+
// Do something with the results
96+
}
97+
98+
// Boost 1.87
99+
void lookup(mysql::any_connection& conn, int id)
100+
{
101+
// Execute your query
102+
mysql::static_results<user> res;
103+
conn.execute(mysql::with_params("SELECT * FROM user WHERE id = {}", id), res);
104+
105+
// Do something with the results
106+
}
107+
```
108+
109+
Since I already talked about this feature in [my last post](https://cppalliance.org/ruben/2024/10/20/Ruben2024Q3Update.html),
110+
I won't delve into more detail here.
111+
112+
### Connection pools
113+
114+
Might be the most requested feature in the library. Establishing sessions is costly, especially if TLS is enabled.
115+
Maintaining connections alive and reconnecting them on failure is also non-trivial.
116+
[Connection pools](https://www.boost.org/doc/libs/master/libs/mysql/doc/html/mysql/tutorial_connection_pool.html)
117+
do both for you, so you can focus on your queries, rather than on the infrastructure:
118+
119+
```cpp
120+
// Boost 1.87. There's no equivalent in previous versions!
121+
int main()
122+
{
123+
asio::io_context ctx;
124+
125+
// pool_params contains configuration for the pool.
126+
mysql::pool_params params {
127+
.server_address = mysql::host_and_port("my_server_hostname.com");
128+
.username = "my_username",
129+
.password = "my_password",
130+
.database = "my_database",
131+
};
132+
133+
// Create the pool and run it. async_run maintains the connections healthy
134+
mysql::connection_pool pool(ctx, std::move(params));
135+
pool.async_run(asio::detached);
136+
137+
// ...
138+
}
139+
140+
asio::awaitable<void> lookup(mysql::connection_pool& pool, int id)
141+
{
142+
// Get a connection from the pool. We don't need to connect or close the connection
143+
mysql::pooled_connection conn = co_await pool.async_get_connection();
144+
145+
// Execute your query
146+
mysql::static_results<user> res;
147+
co_await conn->async_execute(mysql::with_params("SELECT * FROM user WHERE id = {}", id), res);
148+
149+
// Do something with the results
150+
}
151+
```
152+
153+
### Built-in diagnostics in exceptions when using async functions
154+
155+
MySQL may produce diagnostic text when queries fail. You can get this passing a `diagnostics`
156+
object that will be populated on error. This, combined with Asio's built-in error checking,
157+
made using throwing async functions cumbersome. As I already explained in
158+
[my previous post](https://cppalliance.org/ruben/2024/10/20/Ruben2024Q3Update.html),
159+
`with_diagnostics` and default completion tokens solve this problem:
160+
161+
```cpp
162+
// Boost 1.86
163+
asio::awaitable<void> handle_request(mysql::tcp_ssl_connection& conn)
164+
{
165+
mysql::results r;
166+
mysql::diagnostics diag;
167+
auto [ec] = co_await conn.async_execute("SELECT 1", r, diag, asio::as_tuple(asio::deferred));
168+
mysql::throw_on_error(ec, diag);
169+
}
170+
171+
// Boost 1.87
172+
asio::awaitable<void> handle_request(mysql::any_connection& conn)
173+
{
174+
mysql::results r;
175+
co_await conn.async_execute("SELECT 1", r);
176+
}
177+
```
178+
179+
During these last months, I've polished these features. I've fix a myriad of small
180+
issues in `connection_pool`, made `mysql::sequence` owning (and thus easier to use
181+
as argument to `with_params`), and made `mysql::with_diagnostics` more interoperable
182+
with other tokens, like `asio::as_tuple`.
183+
184+
## A new exposition for Boost.MySQL
185+
186+
With great power comes great responsibility. I strongly believe that these new, exciting features
187+
are almost worthless if they are not properly explained. I wrote Boost.MySQL docs some time ago,
188+
and user experience has changed my mind on how an exposition should be.
189+
I've re-written many of the pages for this release, making them more practical, with more examples and use cases.
190+
I've introduced not one, but seven tutorials, slowly walking the user through the most common MySQL
191+
(and Asio) concepts to get them up to speed. And I've added new examples out of questions I received on GitHub.
192+
193+
The old discussion used sync functions to expose library concepts, because they were by far
194+
the easiest to use. This lack of async examples led many users down to using sync functions
195+
when they shouldn't. Now that C++20 coroutines yield clean code, I've re-written part of
196+
the exposition to use them, providing more guidance on async patterns.
197+
As not everyone can (or want) to use them, I've also added some pages on how
198+
to port C++20 coroutine code to other completion styles.
199+
200+
Writing all this has proven to be really time-consuming. Some might think of it as unexciting,
201+
but I hope my users will appreciate it. I'd like to thank the C++ Alliance sponsorship here,
202+
because these new docs wouldn't be possible without it.
203+
204+
My next step here will be migrating the docs to Asciidoc, so they get a "younger"
205+
look and feel. This implies moving from the old Docca toolchain to an Asciidoc generator
206+
like [MrDocs](https://www.mrdocs.com/). I've had the pleasure to be an early user of the tool,
207+
and been able to provide some (hopefully useful) feedback to its authors.
208+
My thank you to Allan, Krystian and Fernando here.
209+
210+
## New citizens in Boost: MQTT5 and Hash2
211+
212+
It's been some intense months in Boost. I've had the pleasure to participate in three Boost reviews: a [MQTT5 Asio-based library](https://github.com/mireo/async-mqtt5/), [an SQLite wrapper](https://klemens.dev/sqlite/) and a [hashing library](https://pdimov.github.io/hash2/doc/html/hash2.html).
213+
214+
I've been specially involved in the first one, since Asio is one of my main areas of expertise. With this library, our Asio ecosystem grows, and with it, the overall usefulness of Boost.
215+
216+
## Other contributions
217+
218+
One of my features that I implemented in Boost.MySQL required me to write a `std::to_array` backport.
219+
I've contributed it to [Boost.Compat](https://www.boost.org/doc/libs/1_87_0/libs/compat/doc/html/compat.html#to_array),
220+
with the help of its maintainer, Peter Dimov. As always, a great learning opportunity.
221+
222+
I've also helped with some maintenance tasks in Boost.Redis.

0 commit comments

Comments
 (0)