Added UNIX typedefs and an example

This commit is contained in:
ruben 2020-04-13 16:33:46 +01:00
parent f8a5904d0b
commit d94bc75f00
6 changed files with 132 additions and 2 deletions

View File

@ -1,3 +1,9 @@
UNIX socket
Network functions for UNIX sockets (generic would be better)
Test suite for UNIX sockets (and maybe SSL too)
Conditionally build/run stuff for UNIX sockets
Config files for CIs to know where UNIX socket is
Docs
Better docs
Breaking up the tutorial in pieces
Explaining the different overloads and async methods available
@ -19,15 +25,19 @@ Usability
Metadata in rows: being able to index by name
Iterators for sync resultset iteration
Consideration of timezones
Timeouts
Retries
Connection pool
Types
Decimal
Bit
Geometry
UNIX socket connection
connection::connect that handles TCP/Unix and MySQL connect
connection::run_sql that hides the resultset concept
Consider if header-only is a good idea
Technical debt
Bad serialize(value.value) somewhere
Valgrindize
Integ tests for different default auth plugins
Integ tests for not enough capabilities
Integ tests for ssl_mode::enable and SSL not available

View File

@ -22,6 +22,7 @@ set(MYSQL_EXAMPLES
query_async_futures
metadata
prepared_statements
unix_socket
)
# We will autogenerate run_examples.bat and run_examples.sh, which will

105
example/unix_socket.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "boost/mysql/connection.hpp"
#include <boost/asio/io_service.hpp>
#include <boost/system/system_error.hpp>
#include <iostream>
/**
* For this example, we will be using the 'mysql_asio_examples' database.
* You can get this database by running db_setup.sql.
* This example assumes you are connecting to MySQL server using
* a UNIX socket. The socket path can be configured using command line
* arguments, and defaults to /tmp/mysql.sock
*
* This example uses synchronous functions and handles errors using exceptions.
*/
void print_employee(const boost::mysql::row& employee)
{
using boost::mysql::operator<<; // Required for mysql::value objects to be streamable, due to ADL rules
std::cout << "Employee '"
<< employee.values()[0] << " " // first_name (type std::string_view)
<< employee.values()[1] << "' earns " // last_name (type std::string_view)
<< employee.values()[2] << " dollars yearly\n"; // salary (type double)
}
void main_impl(int argc, char** argv)
{
if (argc != 3 && argc != 4)
{
std::cerr << "Usage: " << argv[0] << " <username> <password> [<socket-path>]\n";
exit(1);
}
const char* socket_path = "/tmp/mysql.sock";
if (argc == 4)
{
socket_path = argv[3];
}
/**
* 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::connection_params params (
argv[1], // username
argv[2], // password
"mysql_asio_examples" // database to use; leave empty or omit the parameter for no database
);
// Note: by default, SSL will be used if the server supports it.
// connection_params accepts an optional ssl_options argument
// determining whether to use SSL or not. See ssl_options and ssl_mode
// documentation for further details on SSL.
boost::asio::io_context ctx;
// Connection to the MySQL server, over a UNIX socket
boost::mysql::unix_connection conn (ctx);
conn.next_layer().connect(ep); // next_level() returns a boost::asio::local::stream_protocol::socket
conn.handshake(params); // Authenticates to the MySQL server
const char* sql = "SELECT first_name, last_name, salary FROM employee WHERE company_id = 'HGS'";
boost::mysql::unix_resultset result = conn.query(sql);
// Get all the rows in the resultset
std::vector<boost::mysql::owning_row> employees = result.fetch_all();
for (const auto& employee: employees)
{
print_employee(employee);
}
// We can issue any SQL statement, not only SELECTs. In this case, the returned
// resultset will have no fields and no rows
sql = "UPDATE employee SET salary = 10000 WHERE first_name = 'Underpaid'";
result = conn.query(sql);
assert(result.fields().size() == 0); // fields() returns a vector containing metadata about the query fields
// Check we have updated our poor intern salary
result = conn.query("SELECT salary FROM employee WHERE first_name = 'Underpaid'");
auto rows = result.fetch_all();
assert(rows.size() == 1);
[[maybe_unused]] auto salary = std::get<double>(rows[0].values()[0]);
assert(salary == 10000);
}
int main(int argc, char** argv)
{
try
{
main_impl(argc, argv);
}
catch (const boost::system::system_error& err)
{
std::cerr << "Error: " << err.what() << ", error code: " << err.code() << std::endl;
return 1;
}
catch (const std::exception& err)
{
std::cerr << "Error: " << err.what() << std::endl;
return 1;
}
}

View File

@ -10,6 +10,7 @@
#include "boost/mysql/prepared_statement.hpp"
#include "boost/mysql/connection_params.hpp"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/local/stream_protocol.hpp>
/**
* \defgroup connection Connection
@ -163,7 +164,9 @@ public:
*/
using tcp_connection = connection<boost::asio::ip::tcp::socket>;
// TODO: UNIX socket connection
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) || defined(BOOST_MYSQL_DOXYGEN)
using unix_connection = connection<boost::asio::local::stream_protocol::socket>;
#endif
/**
* \ingroup connection

View File

@ -6,6 +6,8 @@
#include "boost/mysql/detail/protocol/prepared_statement_messages.hpp"
#include "boost/mysql/detail/auxiliar/async_result_macro.hpp"
#include <optional>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/local/stream_protocol.hpp>
/**
* \defgroup stmt Prepared statements
@ -179,6 +181,10 @@ public:
*/
using tcp_prepared_statement = prepared_statement<boost::asio::ip::tcp::socket>;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) || defined(BOOST_MYSQL_DOXYGEN)
using unix_prepared_statement = prepared_statement<boost::asio::local::stream_protocol::socket>;
#endif
} // mysql
} // boost

View File

@ -9,6 +9,7 @@
#include "boost/mysql/detail/network_algorithms/common.hpp" // deserialize_row_fn
#include "boost/mysql/detail/auxiliar/async_result_macro.hpp"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/local/stream_protocol.hpp>
#include <cassert>
/**
@ -204,6 +205,10 @@ public:
*/
using tcp_resultset = resultset<boost::asio::ip::tcp::socket>;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) || defined(BOOST_MYSQL_DOXYGEN)
using unix_resultset = resultset<boost::asio::local::stream_protocol::socket>;
#endif
} // mysql
} // boost