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

UNIX sockets

This example demonstrates how to establish a connection to a MySQL server using a UNIX domain socket. The path to the UNIX socket can be passed in as third parameter in the command line, and defaults to /var/run/mysqld/mysqld.sock, the default on most systems.

The example employs synchronous functions with exceptions as error handling. See this section for more info on error handling.

This example assumes you have gone through the setup.

#include <boost/mysql/error_with_diagnostics.hpp>
#include <boost/mysql/handshake_params.hpp>
#include <boost/mysql/results.hpp>
#include <boost/mysql/row_view.hpp>
#include <boost/mysql/statement.hpp>
#include <boost/mysql/unix.hpp>

#include <boost/asio/io_context.hpp>
#include <boost/asio/local/stream_protocol.hpp>

#include <iostream>

void print_employee(boost::mysql::row_view employee)
{
    std::cout << "Employee '" << employee.at(0) << " "   // first_name (string)
              << employee.at(1) << "' earns "            // last_name  (string)
              << employee.at(2) << " dollars yearly\n";  // salary     (double)
}

#define ASSERT(expr)                                          \
    if (!(expr))                                              \
    {                                                         \
        std::cerr << "Assertion failed: " #expr << std::endl; \
        exit(1);                                              \
    }

/**
 * UNIX sockets are only available on, er, UNIX systems. Typedefs for
 * UNIX socket-based connections are only available in UNIX systems.
 * Check for BOOST_ASIO_HAS_LOCAL_SOCKETS to know if UNIX socket
 * typedefs are available in your system.
 */
#ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS

void main_impl(int argc, char** argv)
{
    if (argc != 3 && argc != 4)
    {
        std::cerr << "Usage: " << argv[0] << " <username> <password> [<socket-path>] [<company-id>]\n";
        exit(1);
    }

    const char* socket_path = argc >= 4 ? argv[3] : "/var/run/mysqld/mysqld.sock";

    // The company_id whose employees we will be listing. This
    // is user-supplied input, and should be treated as untrusted.
    const char* company_id = argc == 5 ? argv[4] : "HGS";

    // Connection parameters that tell us where and how to connect to the MySQL server.
    // There are two types of parameters:
    //   - UNIX-level connection parameters, identifying the UNIX socket to connect to.
    //   - MySQL level parameters: database credentials and schema to use.
    boost::asio::local::stream_protocol::endpoint ep(socket_path);
    boost::mysql::handshake_params params(
        argv[1],                // username
        argv[2],                // password
        "boost_mysql_examples"  // database to use; leave empty or omit the parameter for no
                                // database
    );

    boost::asio::io_context ctx;

    // Connection to the MySQL server, over a UNIX socket. Note that we don't need
    // to use SSL when using UNIX sockets because it's restricted to the local machine,
    // so MySQL considers it secure, even if it's not encrypted.
    boost::mysql::unix_connection conn(ctx);
    conn.connect(ep, params);  // UNIX socket connect and MySQL handshake

    // We will be using company_id, which is untrusted user input, so we will use a prepared
    // statement.
    boost::mysql::statement stmt = conn.prepare_statement(
        "SELECT first_name, last_name, salary FROM employee WHERE company_id = ?"
    );

    // Execute the statement
    boost::mysql::results result;
    conn.execute(stmt.bind(company_id), result);

    // Print employees
    for (boost::mysql::row_view employee : result.rows())
    {
        print_employee(employee);
    }

    // Notify the MySQL server we want to quit, then close the underlying connection.
    conn.close();
}

#else

void main_impl(int, char**) { std::cout << "Sorry, your system does not support UNIX sockets" << std::endl; }

#endif

int main(int argc, char** argv)
{
    try
    {
        main_impl(argc, argv);
    }
    catch (const boost::mysql::error_with_diagnostics& err)
    {
        // Some errors include additional diagnostics, like server-provided error messages.
        // Security note: diagnostics::server_message may contain user-supplied values (e.g. the
        // field value that caused the error) and is encoded using to the connection's character set
        // (UTF-8 by default). Treat is as untrusted input.
        std::cerr << "Error: " << err.what() << ", error code: " << err.code() << '\n'
                  << "Server diagnostics: " << err.get_diagnostics().server_message() << std::endl;
        return 1;
    }
    catch (const std::exception& err)
    {
        std::cerr << "Error: " << err.what() << std::endl;
        return 1;
    }
}

PrevUpHomeNext