Appearance
Connections & Pools
The database module manages MySQL connection pools through framework::database::manager. Connection pooling reuses database connections to reduce the overhead of establishing new connections.
Creating a Pool
A pool is a named group of persistent MySQL connections. Create one for each logical database your service uses.
cpp
auto& db = app.get_state()->of_database();
db.create_pool(
"primary", // Pool name
"127.0.0.1", // MySQL host
3306, // MySQL port
"${MYSQL_USER}", // Username
"${MYSQL_PASSWORD}", // Password
"my_database", // Database name
4, // Initial connections opened at startup
32 // Maximum connections the pool can grow to
);Parameters:
| Parameter | Description |
|---|---|
name | Logical name to identify this pool (e.g., "primary", "analytics"). |
host | MySQL server hostname or IP. |
port | MySQL server port (default: 3306). |
user | Authentication username. |
password | Authentication password. |
database | Default database to use. |
initial_size | Number of connections to open immediately. |
max_size | Maximum number of connections. The pool grows on demand up to this limit. |
Running Queries
run(cb, query) — Simple query
Retrieves a connection from the pool, executes the query, and returns the result.
cpp
auto* pool = db.get_pool("primary");
pool->run([](auto ec, const boost::mysql::results& results) {
if (ec) {
fmt::println("Query failed: {}", ec.what());
return;
}
// Iterate over rows
for (auto& row : results.rows()) {
fmt::println("Column 0: {}", row.at(0));
}
}, "SELECT * FROM users");run(cb, query, params) — Parameterized query
Uses ? placeholders to safely bind values. This prevents SQL injection.
cpp
pool->run([](auto ec, auto results) {
if (ec) return;
// Process results
}, "SELECT * FROM users WHERE id = ?", {42});Parameters:
| Parameter | Description |
|---|---|
cb | Callback with (error_code, results). Called on the io_context thread. |
query | SQL query string with optional ? placeholders. |
params | std::vector<boost::mysql::field> of values for placeholders. |
Transactions
begin_transaction(cb) — Start a transaction
Gets a connection from the pool and begins a MySQL transaction.
cpp
pool->begin_transaction([](auto ec, auto tx) {
if (ec) return;
tx->run([](auto ec, auto results) { }, "INSERT INTO ...");
tx->commit([](auto ec) { });
});See Transactions for the full API.
Query Logging
The pool can log every executed query with its duration. Useful for debugging and performance analysis. Query logging is a static (global) feature — enabling it affects all pools. Warning: In production, logged queries accumulate without bound — use flush_query_log() periodically or disable logging after debugging.
cpp
using namespace framework;
using namespace framework::database;
// Enable logging globally for all pools
pool::enable_query_log();
// Run queries...
pool->run(/* ... */);
// Read the global log
auto& log = pool::get_query_log();
for (auto& entry : log) {
fmt::println("Query: {} ({} ms)", entry.query, entry.elapsed_ms);
}
// Disable when done
pool::disable_query_log();
// Clear the log to free memory
pool::flush_query_log();Each log entry contains:
| Field | Description |
|---|---|
query | The SQL query string. |
params | The bound parameters. |
elapsed_ms | Execution time in milliseconds. |
Pool Management
pool_names() — List pools
cpp
auto names = db.pool_names();
// Returns: {"primary", "analytics", ...}resize(new_max_size) — Change capacity
Dynamically adjusts the maximum number of connections.
cpp
pool->resize(64); // Allow up to 64 connectionsinitial_size() / max_size() — Inspect pool config
cpp
auto init = pool->initial_size(); // Initial connection count
auto max = pool->max_size(); // Maximum connection capacityis_stopped() — Check if pool is shut down
cpp
if (pool->is_stopped()) {
// Pool has been shut down
}stop() — Shut down
Closes all connections in the pool. Called automatically during app shutdown.
cpp
pool->stop();