2019-09-24 22:28:59 +00:00
|
|
|
#if __has_include(<mysql.h>)
|
|
|
|
#include <mysql.h>
|
2018-07-25 11:29:26 +00:00
|
|
|
#else
|
2017-01-24 21:07:08 +00:00
|
|
|
#include <mysql/mysql.h>
|
2018-07-25 11:29:26 +00:00
|
|
|
#endif
|
2017-04-14 19:38:56 +00:00
|
|
|
|
2011-03-03 19:57:34 +00:00
|
|
|
#include <mysqlxx/Connection.h>
|
|
|
|
#include <mysqlxx/Exception.h>
|
|
|
|
|
2017-09-09 21:26:02 +00:00
|
|
|
static inline const char* ifNotEmpty(const char* s)
|
|
|
|
{
|
|
|
|
return s && *s ? s : nullptr;
|
|
|
|
}
|
2011-03-03 19:57:34 +00:00
|
|
|
|
|
|
|
namespace mysqlxx
|
|
|
|
{
|
|
|
|
|
2017-01-13 20:37:37 +00:00
|
|
|
LibrarySingleton::LibrarySingleton()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (mysql_library_init(0, nullptr, nullptr))
|
|
|
|
throw Exception("Cannot initialize MySQL library.");
|
2017-01-13 20:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LibrarySingleton::~LibrarySingleton()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
mysql_library_end();
|
2017-01-13 20:37:37 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 03:24:05 +00:00
|
|
|
auto & LibrarySingleton::instance()
|
|
|
|
{
|
|
|
|
static LibrarySingleton instance;
|
|
|
|
return instance;
|
|
|
|
}
|
2011-10-05 20:21:18 +00:00
|
|
|
|
2011-03-03 19:57:34 +00:00
|
|
|
Connection::Connection()
|
2017-04-01 07:20:54 +00:00
|
|
|
: driver(std::make_unique<MYSQL>())
|
2011-03-03 19:57:34 +00:00
|
|
|
{
|
2017-07-18 11:52:46 +00:00
|
|
|
/// MySQL library initialization.
|
2017-04-01 07:20:54 +00:00
|
|
|
LibrarySingleton::instance();
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Connection::Connection(
|
2017-04-01 07:20:54 +00:00
|
|
|
const char* db,
|
|
|
|
const char* server,
|
|
|
|
const char* user,
|
|
|
|
const char* password,
|
|
|
|
unsigned port,
|
2017-07-14 12:45:32 +00:00
|
|
|
const char * socket,
|
2017-09-09 21:26:02 +00:00
|
|
|
const char* ssl_ca,
|
|
|
|
const char* ssl_cert,
|
|
|
|
const char* ssl_key,
|
2017-04-01 07:20:54 +00:00
|
|
|
unsigned timeout,
|
2018-10-01 15:55:21 +00:00
|
|
|
unsigned rw_timeout,
|
2021-02-26 06:49:49 +00:00
|
|
|
bool enable_local_infile,
|
|
|
|
bool opt_reconnect)
|
2018-08-13 06:16:58 +00:00
|
|
|
: Connection()
|
2011-03-03 19:57:34 +00:00
|
|
|
{
|
2021-02-26 06:49:49 +00:00
|
|
|
connect(db, server, user, password, port, socket, ssl_ca, ssl_cert, ssl_key, timeout, rw_timeout, enable_local_infile, opt_reconnect);
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 20:37:37 +00:00
|
|
|
Connection::Connection(const std::string & config_name)
|
2018-08-13 06:16:58 +00:00
|
|
|
: Connection()
|
2017-01-13 20:37:37 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
connect(config_name);
|
2017-01-13 20:37:37 +00:00
|
|
|
}
|
|
|
|
|
2011-03-03 19:57:34 +00:00
|
|
|
Connection::~Connection()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
disconnect();
|
|
|
|
mysql_thread_end();
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Connection::connect(const char* db,
|
2017-12-13 19:55:45 +00:00
|
|
|
const char * server,
|
|
|
|
const char * user,
|
|
|
|
const char * password,
|
2017-04-01 07:20:54 +00:00
|
|
|
unsigned port,
|
2017-07-14 12:45:32 +00:00
|
|
|
const char * socket,
|
2017-12-13 19:55:45 +00:00
|
|
|
const char * ssl_ca,
|
|
|
|
const char * ssl_cert,
|
|
|
|
const char * ssl_key,
|
2017-04-01 07:20:54 +00:00
|
|
|
unsigned timeout,
|
2018-10-01 15:55:21 +00:00
|
|
|
unsigned rw_timeout,
|
2021-02-26 06:49:49 +00:00
|
|
|
bool enable_local_infile,
|
|
|
|
bool opt_reconnect)
|
2011-03-03 19:57:34 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (is_connected)
|
|
|
|
disconnect();
|
2011-03-03 19:57:34 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (!mysql_init(driver.get()))
|
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2018-08-13 06:16:58 +00:00
|
|
|
is_initialized = true;
|
2011-03-03 19:57:34 +00:00
|
|
|
|
2017-07-18 11:52:46 +00:00
|
|
|
/// Set timeouts.
|
2018-06-29 18:06:07 +00:00
|
|
|
if (mysql_options(driver.get(), MYSQL_OPT_CONNECT_TIMEOUT, &timeout))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2011-05-13 16:58:53 +00:00
|
|
|
|
2018-06-29 18:06:07 +00:00
|
|
|
if (mysql_options(driver.get(), MYSQL_OPT_READ_TIMEOUT, &rw_timeout))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2013-03-31 01:16:35 +00:00
|
|
|
|
2018-06-29 18:06:07 +00:00
|
|
|
if (mysql_options(driver.get(), MYSQL_OPT_WRITE_TIMEOUT, &rw_timeout))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2013-03-31 01:16:35 +00:00
|
|
|
|
2018-10-01 15:55:21 +00:00
|
|
|
/// Disable LOAD DATA LOCAL INFILE because it is insecure if necessary.
|
|
|
|
unsigned enable_local_infile_arg = static_cast<unsigned>(enable_local_infile);
|
|
|
|
if (mysql_options(driver.get(), MYSQL_OPT_LOCAL_INFILE, &enable_local_infile_arg))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2011-08-23 17:46:58 +00:00
|
|
|
|
2021-02-26 06:49:49 +00:00
|
|
|
/// See C API Developer Guide: Automatic Reconnection Control
|
|
|
|
if (mysql_options(driver.get(), MYSQL_OPT_RECONNECT, reinterpret_cast<const char *>(&opt_reconnect)))
|
2020-12-03 20:36:10 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
|
|
|
|
2017-09-09 21:26:02 +00:00
|
|
|
/// Specifies particular ssl key and certificate if it needs
|
|
|
|
if (mysql_ssl_set(driver.get(), ifNotEmpty(ssl_key), ifNotEmpty(ssl_cert), ifNotEmpty(ssl_ca), nullptr, nullptr))
|
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
|
|
|
|
|
|
|
if (!mysql_real_connect(driver.get(), server, user, password, db, port, ifNotEmpty(socket), driver->client_flag))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2011-03-03 19:57:34 +00:00
|
|
|
|
2021-01-29 07:57:22 +00:00
|
|
|
/// Sets UTF-8 as default encoding. See https://mariadb.com/kb/en/mysql_set_character_set/
|
|
|
|
if (mysql_set_character_set(driver.get(), "utf8mb4"))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get()));
|
2011-03-16 20:33:39 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
is_connected = true;
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Connection::connected() const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return is_connected;
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Connection::disconnect()
|
|
|
|
{
|
2018-08-13 06:16:58 +00:00
|
|
|
if (!is_initialized)
|
2017-04-01 07:20:54 +00:00
|
|
|
return;
|
2011-03-03 19:57:34 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
mysql_close(driver.get());
|
|
|
|
memset(driver.get(), 0, sizeof(*driver));
|
2018-08-13 06:16:58 +00:00
|
|
|
|
|
|
|
is_initialized = false;
|
2017-04-01 07:20:54 +00:00
|
|
|
is_connected = false;
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Connection::ping()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return is_connected && !mysql_ping(driver.get());
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Query Connection::query(const std::string & str)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return Query(this, str);
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
2011-03-09 20:11:29 +00:00
|
|
|
MYSQL * Connection::getDriver()
|
2011-03-03 19:57:34 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return driver.get();
|
2011-03-03 19:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|