-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from jgaa/actions
Add example
- Loading branch information
Showing
6 changed files
with
274 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
|
||
project(simple_sql_app | ||
DESCRIPTION "Simple example on how to use mysqlpool-cpp" | ||
LANGUAGES CXX | ||
) | ||
|
||
add_executable(${PROJECT_NAME} main.cpp fun_with_sql.cpp) | ||
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) | ||
target_link_libraries(${PROJECT_NAME} mysqlpool) | ||
|
||
target_include_directories(${PROJECT_NAME} PRIVATE | ||
$<BUILD_INTERFACE:${Boost_INCLUDE_DIR}> | ||
$<BUILD_INTERFACE:${MYSQLPOOL_ROOT}/include> | ||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-include> | ||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/external-projects/installed/include> | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> | ||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
$Boost_INCLUDE_DIR | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
|
||
#include <boost/asio.hpp> | ||
|
||
#include "mysqlpool/logging.h" | ||
#include "mysqlpool/mysqlpool.h" | ||
#include "mysqlpool/conf.h" | ||
#include "mysqlpool/config.h" | ||
|
||
using namespace std; | ||
namespace mp = jgaa::mysqlpool; | ||
|
||
|
||
|
||
boost::asio::awaitable<void> ping_the_db_server(mp::Mysqlpool& pool) { | ||
|
||
// Lets get an actual connection to the database | ||
// hande is a Handle to a Connection. | ||
// It will automatically release the connection when it goes out of scope. | ||
auto handle = co_await pool.getConnection(); | ||
|
||
// When we obtain a handle, we can use the native boost.mysql methods. | ||
// Let's try it and ping the server. | ||
// If the server is not available, the async_ping will throw an exception. | ||
|
||
cout << "Pinging the server..." << endl; | ||
co_await handle.connection().async_ping(boost::asio::use_awaitable); | ||
} | ||
|
||
boost::asio::awaitable<void> get_db_version_using_boost_mysql(mp::Mysqlpool& pool) { | ||
|
||
// Lets get an actual connection to the database | ||
auto handle = co_await pool.getConnection(); | ||
|
||
// hande is a Handle to a Connection. | ||
// It will automatically release the connection when it goes out of scope. | ||
|
||
// Now, let's see what version the database server uses, by sending a query: 'SELECT @@version' | ||
// This time we will use proper error handling. | ||
// Please see the boost.mysql documentation for more information. | ||
|
||
boost::mysql::results res; | ||
boost::mysql::diagnostics diag; | ||
const auto [ec] = co_await handle.connection().async_execute("SELECT @@version", res, diag, mp::tuple_awaitable); | ||
if (ec) { | ||
MYSQLPOOL_LOG_ERROR_("Error: " << ec.message() | ||
<< ", diag client: " << diag.client_message() | ||
<< ", diag server: " << diag.server_message()); | ||
co_return; | ||
} | ||
if (res.has_value() && !res.rows().empty()) { | ||
const auto db_version = res.rows()[0][0].as_string(); | ||
cout << "Database version: " << db_version << endl; | ||
} | ||
|
||
co_return; | ||
} | ||
|
||
|
||
boost::asio::awaitable<void> get_db_version(mp::Mysqlpool& pool) { | ||
|
||
// Now, lets do the same as above, but with less code. | ||
// Note that we leave most of the error-handling to Mysqlpool. | ||
// We also let Mysqlpool handle the connection, and release it before exec() returns. | ||
// If there is a problem, Mysqlpool will retry if appropriate. | ||
// If not, it will throw an exception. | ||
|
||
const auto res = co_await pool.exec("SELECT @@version"); | ||
|
||
// if pool.exec() returned, we know that the result is not empty. | ||
assert(!res.empty()); | ||
|
||
// We still have to check that the db server sent us something. | ||
if (!res.rows().empty()) { | ||
const auto db_version = res.rows()[0][0].as_string(); | ||
cout << "Database version: " << db_version << endl; | ||
} | ||
|
||
co_return; | ||
} | ||
|
||
// Entry point from main() | ||
void run_examples(const mp::DbConfig& config){ | ||
|
||
|
||
// Create an io_context, which is the heart of the boost.asio library. | ||
// It will manage all asynchronous operations. | ||
boost::asio::io_context ctx; | ||
|
||
// Create an instance of Mysqlool | ||
// It will connect to the database and keep a pool of connections. | ||
mp::Mysqlpool pool(ctx, config); | ||
|
||
// Start a coroutine context, and work in it until we are done. | ||
auto res = boost::asio::co_spawn(ctx, [&]() -> boost::asio::awaitable<void> { | ||
// Initialzie the connection pool. | ||
// It will connect to the database and keep a pool of connections. | ||
co_await pool.init(); | ||
|
||
// Run trough the examples | ||
co_await ping_the_db_server(pool); | ||
co_await get_db_version_using_boost_mysql(pool); | ||
co_await get_db_version(pool); | ||
|
||
// Gracefully shut down the connection-pool. | ||
co_await pool.close(); | ||
|
||
}, boost::asio::use_future); | ||
|
||
// Let the main thread run the boost.asio event loop. | ||
ctx.run(); | ||
|
||
try { | ||
// Now, let's deal with exceptions from the coroutines, if any | ||
res.get(); | ||
} catch (const exception& ex) { | ||
MYSQLPOOL_LOG_ERROR_("Caught exception from coroutine: " << ex.what()); | ||
} | ||
|
||
MYSQLPOOL_LOG_INFO_("Example run is done: "); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
|
||
#include <iostream> | ||
#include <filesystem> | ||
#include <boost/program_options.hpp> | ||
#include <boost/asio.hpp> | ||
|
||
#include "mysqlpool/logging.h" | ||
#include "mysqlpool/mysqlpool.h" | ||
#include "mysqlpool/conf.h" | ||
#include "mysqlpool/config.h" | ||
|
||
#ifdef _MSC_VER | ||
# include <stdlib.h> | ||
// Use _putenv_s when compiled with Microsoft's compiler | ||
// Thank you Microsoft! | ||
# define setenv(key, value, ignore) _putenv_s(key, value) | ||
#endif | ||
|
||
using namespace std; | ||
namespace mp = jgaa::mysqlpool; | ||
|
||
extern void run_examples(const mp::DbConfig& config); | ||
|
||
int main(int argc, char* argv[]) { | ||
// Don't make the app crash with an uincaught exception if Linux can't deal with your locale setting! | ||
// In stead, switch to the "C" locale which hopefully works. | ||
try { | ||
locale loc(""); | ||
} catch (const std::exception&) { | ||
cout << "Locales in Linux are fundamentally broken. Never worked. Never will. Overriding the current mess with LC_ALL=C" << endl; | ||
setenv("LC_ALL", "C", 1); | ||
} | ||
|
||
std::string log_level = "info"; | ||
mp::DbConfig config; | ||
|
||
const auto appname = filesystem::path(argv[0]).stem().string(); | ||
|
||
namespace po = boost::program_options; | ||
po::options_description general("Options"); | ||
general.add_options() | ||
("help,h", "Print help and exit") | ||
("version,v", "Print version and exit") | ||
("log-to-console,C", | ||
po::value(&log_level)->default_value(log_level), | ||
"Log-level to the console; one of 'info', 'debug', 'trace'. Empty string to disable.") | ||
; | ||
po::options_description db_opts("Database options"); | ||
db_opts.add_options() | ||
("db-user", | ||
po::value(&config.username), | ||
"Mysql user to use when logging into the mysql server") | ||
("db-passwd", | ||
po::value(&config.password), | ||
"Mysql password to use when logging into the mysql server") | ||
("db-name", | ||
po::value(&config.database)->default_value(config.database), | ||
"Database to use") | ||
("db-host", | ||
po::value(&config.host)->default_value(config.host), | ||
"Hostname or IP address for the database server") | ||
("db-port", | ||
po::value(&config.port)->default_value(config.port), | ||
"Port number for the database server") | ||
("db-min-connections", | ||
po::value(&config.min_connections)->default_value(config.min_connections), | ||
"Max concurrent connections to the database server") | ||
("db-max-connections", | ||
po::value(&config.max_connections)->default_value(config.max_connections), | ||
"Max concurrent connections to the database server") | ||
("db-retry-connect", | ||
po::value(&config.retry_connect)->default_value(config.retry_connect), | ||
"Retry connect to the database-server # times on startup. Useful when using containers, where nextappd may be running before the database is ready.") | ||
("db-retry-delay", | ||
po::value(&config.retry_connect_delay_ms)->default_value(config.retry_connect_delay_ms), | ||
"Milliseconds to wait between connection retries") | ||
; | ||
|
||
po::options_description cmdline_options; | ||
cmdline_options.add(general).add(db_opts); | ||
po::variables_map vm; | ||
try { | ||
po::store(po::command_line_parser(argc, argv).options(cmdline_options).run(), vm); | ||
po::notify(vm); | ||
} catch (const std::exception& ex) { | ||
cerr << appname | ||
<< " Failed to parse command-line arguments: " << ex.what() << endl; | ||
return -1; | ||
} | ||
|
||
if (vm.count("help")) { | ||
std::cout <<appname << " [options]"; | ||
std::cout << cmdline_options << std::endl; | ||
return -2; | ||
} | ||
|
||
if (vm.count("version")) { | ||
std::cout << appname << endl | ||
<< "Using C++ standard " << __cplusplus << endl | ||
<< "Boost " << BOOST_LIB_VERSION << endl | ||
<< "Platform " << BOOST_PLATFORM << endl | ||
<< "Compiler " << BOOST_COMPILER << endl | ||
<< "Build date " <<__DATE__ << endl | ||
<< "Mysqlpool " << MYSQLPOOL_VERSION << endl; | ||
return -3; | ||
} | ||
|
||
// Set up logging | ||
// In this example we use this macro to use whatever log framework | ||
// mysqlpool is configured to use. | ||
// In your app, you will typically choose what log framework to use | ||
// and configure it in your app. | ||
MYSQLPOOL_TEST_LOGGING_SETUP(log_level); | ||
|
||
MYSQLPOOL_LOG_INFO_(appname << " starting up."); | ||
|
||
try { | ||
run_examples(config); | ||
} catch (const exception& ex) { | ||
MYSQLPOOL_LOG_ERROR_("Caught exception: " << ex.what()); | ||
return -5; | ||
} | ||
|
||
MYSQLPOOL_LOG_INFO_(appname << " is done!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
"boost-log", | ||
"boost-mysql", | ||
"boost-uuid", | ||
"boost-program-options", | ||
"zlib", | ||
"openssl", | ||
"gtest" | ||
|