...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
To use the static interface, we must first define a data structure that describes
the shape of your rows. We recommend using Boost.Describe
for this. We define a plain struct
with the fields returned by your our and annotate it with BOOST_DESCRIBE_STRUCT
to enable reflection on it.
For example, given the following table definition and query:
const char* table_definition = R"%( CREATE TEMPORARY TABLE posts ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR (256) NOT NULL, body TEXT NOT NULL ) )%"; const char* query = "SELECT id, title, body FROM posts";
We can define our row type like this:
// We can use a plain struct with ints and strings to describe our rows. // This must be placed at the namespace level struct post { int id; std::string title; std::string body; }; // We must use Boost.Describe to add reflection capabilities to post. // We must list all the fields that should be populated by Boost.MySQL BOOST_DESCRIBE_STRUCT(post, (), (id, title, body))
To run the query, we can write:
static_results<post> result; conn.execute(query, result); for (const post& p : result.rows()) { // Process the post as required std::cout << "Title: " << p.title << "\n" << p.body << "\n"; }
Note that static_results::rows
returns a boost::span
object, which is a C++11 backport of
std::span
. The span points into memory owned by
the static_results
object.
Care must be taken not to use this view object after the static_results
goes out of scope.
Columns in the query are matched to fields in the struct by name. If a struct field cannot be matched to any query column, an error is issued. Extra columns in the query are ignored.
If your query contains columns with names that don't qualify as C++ identifiers, you can use SQL aliases. For example, given this struct:
struct statistics { std::string company; double average; double max_value; }; BOOST_DESCRIBE_STRUCT(statistics, (), (company, average, max_value))
You can write your query as:
// Summing 0e0 is MySQL way to cast a DECIMAL field to DOUBLE const char* sql = R"%( SELECT IFNULL(AVG(salary), 0.0) + 0e0 AS average, IFNULL(MAX(salary), 0.0) + 0e0 AS max_value, company_id AS company FROM employee GROUP BY company_id )%"; static_results<statistics> result; conn.execute(sql, result);
You can also use std::tuple
s as row types. This can be handy for
simple queries:
static_results<std::tuple<std::int64_t>> result; conn.execute("SELECT COUNT(*) FROM employee", result); std::cout << "Number of employees: " << std::get<0>(result.rows()[0]) << "\n";
Fields in tuples are matched to query columns by order. The query must return as many columns as fields the tuple has, at least. Any extra trailing columns in the query are ignored.
The static interface will try to validate as soon as possible that the provided row type is compatible with the schema returned by the server. This process is known as metadata checking, and is performed before reading any data. The following checks are performed:
std::int32_t
is compatible with TINYINT
(1 byte integer), but not with
BIGINT
(8 byte integer).
For a full list of allowable field types, refer
to this table.
NULL
, your type
must account for it. You can use std::optional<T>
or boost::optional<T>
for these columns.
For example, if your table is defined like this:
const char* table_definition = R"%( CREATE TEMPORARY TABLE posts_v2 ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR (256) NOT NULL, body TEXT ) )%";
Using the post
type we defined
above will cause an error, because the body
field may be NULL
, but our
type doesn't account for it. In this case, the correct definition would be:
struct post_v2 { int id; std::string title; std::optional<std::string> body; // body may be NULL }; BOOST_DESCRIBE_STRUCT(post_v2, (), (id, title, body))
You can use both with the dynamic interface. Please refer to the sections on multi-resultset operations and multi-function operations for more information.
Using the static interface requires C++14. The BOOST_MYSQL_CXX14
test macro is defined only if the static interface is supported. Including
the static interface headers on an unsupported compiler doesn't cause any error,
but classes like static_results
and static_execution_state
are not defined. The test macro is brought on scope by any of the static interface
headers.
All the types used within your Describe structs or tuples must be within the
following table. A Describe struct or tuple composed of valid field types models
the StaticRow
concept.
The following table is a reference of the C++ types that can be used in a
StaticRow
and their compatibility
with MySQL database types:
C++ type |
Compatible with... |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Any type compatible with |
|
Any type compatible with |