mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-20 11:47:47 +00:00
254 lines
7.2 KiB
C++
254 lines
7.2 KiB
C++
#include "Connection.h"
|
|
#include "MySqlBase.h"
|
|
#include "Statement.h"
|
|
#include "PreparedStatement.h"
|
|
#include <mysql.h>
|
|
|
|
#include <vector>
|
|
|
|
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
|
|
const std::string& hostName,
|
|
const std::string& userName,
|
|
const std::string& password,
|
|
uint16_t port ) :
|
|
m_pBase( pBase ),
|
|
m_bConnected( false )
|
|
{
|
|
m_pRawCon = mysql_init( nullptr );
|
|
if( mysql_real_connect( m_pRawCon, hostName.c_str(), userName.c_str(), password.c_str(),
|
|
nullptr, port, nullptr, 0) == nullptr )
|
|
throw std::runtime_error( mysql_error( m_pRawCon ) );
|
|
m_bConnected = true;
|
|
|
|
}
|
|
|
|
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
|
|
const std::string& hostName,
|
|
const std::string& userName,
|
|
const std::string& password,
|
|
const optionMap& options,
|
|
uint16_t port ) :
|
|
m_pBase( pBase )
|
|
{
|
|
m_pRawCon = mysql_init( nullptr );
|
|
// Different mysql versions support different options, for now whatever was unsupporter here was commented out
|
|
// but left there.
|
|
for( auto entry : options )
|
|
{
|
|
switch( entry.first )
|
|
{
|
|
// integer based options
|
|
case MYSQL_OPT_CONNECT_TIMEOUT:
|
|
case MYSQL_OPT_PROTOCOL:
|
|
case MYSQL_OPT_READ_TIMEOUT:
|
|
// case MYSQL_OPT_SSL_MODE:
|
|
// case MYSQL_OPT_RETRY_COUNT:
|
|
case MYSQL_OPT_WRITE_TIMEOUT:
|
|
// case MYSQL_OPT_MAX_ALLOWED_PACKET:
|
|
// case MYSQL_OPT_NET_BUFFER_LENGTH:
|
|
{
|
|
uint32_t optVal = std::stoi( entry.second, nullptr, 10 );
|
|
setOption( entry.first, optVal );
|
|
}
|
|
break;
|
|
|
|
// bool based options
|
|
// case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
|
|
// case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
|
|
case MYSQL_OPT_COMPRESS:
|
|
case MYSQL_OPT_GUESS_CONNECTION:
|
|
case MYSQL_OPT_LOCAL_INFILE:
|
|
case MYSQL_OPT_RECONNECT:
|
|
// case MYSQL_OPT_SSL_ENFORCE:
|
|
// case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
|
|
case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
|
|
case MYSQL_OPT_USE_REMOTE_CONNECTION:
|
|
case MYSQL_REPORT_DATA_TRUNCATION:
|
|
case MYSQL_SECURE_AUTH:
|
|
{
|
|
my_bool optVal = entry.second == "0" ? 0 : 1;
|
|
setOption( entry.first, &optVal );
|
|
}
|
|
break;
|
|
|
|
// string based options
|
|
// case MYSQL_DEFAULT_AUTH:
|
|
// case MYSQL_OPT_BIND:
|
|
// case MYSQL_OPT_SSL_CA:
|
|
// case MYSQL_OPT_SSL_CAPATH:
|
|
// case MYSQL_OPT_SSL_CERT:
|
|
// case MYSQL_OPT_SSL_CIPHER:
|
|
// case MYSQL_OPT_SSL_CRL:
|
|
// case MYSQL_OPT_SSL_CRLPATH:
|
|
// case MYSQL_OPT_SSL_KEY:
|
|
// case MYSQL_OPT_TLS_VERSION:
|
|
// case MYSQL_PLUGIN_DIR:
|
|
case MYSQL_READ_DEFAULT_FILE:
|
|
case MYSQL_READ_DEFAULT_GROUP:
|
|
// case MYSQL_SERVER_PUBLIC_KEY:
|
|
case MYSQL_SET_CHARSET_DIR:
|
|
case MYSQL_SET_CHARSET_NAME:
|
|
case MYSQL_SET_CLIENT_IP:
|
|
case MYSQL_SHARED_MEMORY_BASE_NAME:
|
|
{
|
|
setOption( entry.first, entry.second.c_str() );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw std::runtime_error( "Unknown option: " + std::to_string( entry.first ) );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if( mysql_real_connect( m_pRawCon, hostName.c_str(), userName.c_str(), password.c_str(),
|
|
nullptr, port, nullptr, 0) == nullptr )
|
|
throw std::runtime_error( mysql_error( m_pRawCon ) );
|
|
|
|
}
|
|
|
|
|
|
Mysql::Connection::~Connection()
|
|
{
|
|
}
|
|
|
|
void Mysql::Connection::setOption( enum mysqlOption option, const void *arg )
|
|
{
|
|
|
|
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), arg ) != 0 )
|
|
throw std::runtime_error( "Connection::setOption failed!" );
|
|
|
|
}
|
|
|
|
void Mysql::Connection::setOption( enum mysqlOption option, uint32_t arg )
|
|
{
|
|
|
|
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), &arg ) != 0 )
|
|
throw std::runtime_error( "Connection::setOption failed!" );
|
|
|
|
}
|
|
|
|
void Mysql::Connection::setOption( enum mysqlOption option, const std::string& arg )
|
|
{
|
|
|
|
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), arg.c_str() ) != 0 )
|
|
throw std::runtime_error( "Connection::setOption failed!" );
|
|
|
|
}
|
|
|
|
void Mysql::Connection::close()
|
|
{
|
|
mysql_close( m_pRawCon );
|
|
m_bConnected = false;
|
|
}
|
|
|
|
bool Mysql::Connection::isClosed() const
|
|
{
|
|
return !m_bConnected;
|
|
}
|
|
|
|
std::shared_ptr< Mysql::MySqlBase > Mysql::Connection::getMySqlBase() const
|
|
{
|
|
return m_pBase;
|
|
}
|
|
|
|
void Mysql::Connection::setAutoCommit( bool autoCommit )
|
|
{
|
|
auto b = static_cast< my_bool >( autoCommit == true ? 1 : 0 );
|
|
if( mysql_autocommit( m_pRawCon, b ) != 0 )
|
|
throw std::runtime_error( "Connection::setAutoCommit failed!" );
|
|
}
|
|
|
|
bool Mysql::Connection::getAutoCommit()
|
|
{
|
|
// TODO: should be replaced with wrapped sql query function once available
|
|
std::string query("SELECT @@autocommit");
|
|
auto res = mysql_real_query( m_pRawCon, query.c_str(), query.length() );
|
|
|
|
if( res != 0 )
|
|
throw std::runtime_error( "Query failed!" );
|
|
|
|
auto pRes = mysql_store_result( m_pRawCon );
|
|
auto row = mysql_fetch_row( pRes );
|
|
|
|
uint32_t ac = atoi( row[0] );
|
|
|
|
return ac != 0;
|
|
}
|
|
|
|
void Mysql::Connection::beginTransaction()
|
|
{
|
|
auto stmt = createStatement();
|
|
stmt->execute( "START TRANSACTION;" );
|
|
}
|
|
|
|
void Mysql::Connection::commitTransaction()
|
|
{
|
|
auto stmt = createStatement();
|
|
stmt->execute( "COMMIT" );
|
|
}
|
|
|
|
void Mysql::Connection::rollbackTransaction()
|
|
{
|
|
auto stmt = createStatement();
|
|
stmt->execute( "ROLLBACK" );
|
|
}
|
|
|
|
std::string Mysql::Connection::escapeString( const std::string &inData )
|
|
{
|
|
std::unique_ptr< char[] > buffer( new char[inData.length() * 2 + 1] );
|
|
if( !buffer.get() )
|
|
return "";
|
|
unsigned long return_len = mysql_real_escape_string( m_pRawCon, buffer.get(),
|
|
inData.c_str(), static_cast< unsigned long > ( inData.length() ) );
|
|
return std::string( buffer.get(), return_len );
|
|
}
|
|
|
|
void Mysql::Connection::setSchema( const std::string &schema )
|
|
{
|
|
if( mysql_select_db( m_pRawCon, schema.c_str() ) != 0 )
|
|
throw std::runtime_error( "Current database could not be changed to " + schema );
|
|
}
|
|
|
|
std::shared_ptr< Mysql::Statement > Mysql::Connection::createStatement()
|
|
{
|
|
return std::make_shared< Mysql::Statement >( shared_from_this() );
|
|
}
|
|
|
|
MYSQL* Mysql::Connection::getRawCon()
|
|
{
|
|
return m_pRawCon;
|
|
}
|
|
|
|
std::string Mysql::Connection::getError()
|
|
{
|
|
auto mysqlError = mysql_error( m_pRawCon );
|
|
if( mysqlError )
|
|
return std::string( mysqlError );
|
|
return "";
|
|
}
|
|
|
|
std::shared_ptr< Mysql::PreparedStatement > Mysql::Connection::prepareStatement( const std::string &sql )
|
|
{
|
|
MYSQL_STMT* stmt = mysql_stmt_init( getRawCon() );
|
|
|
|
if( !stmt )
|
|
throw std::runtime_error( "Could not init prepared statement: " + getError() );
|
|
|
|
if( mysql_stmt_prepare( stmt, sql.c_str(), sql.size() ) )
|
|
throw std::runtime_error( "Could not prepare statement: " + getError() );
|
|
|
|
return std::make_shared< PreparedStatement >( stmt, shared_from_this() );
|
|
}
|
|
|
|
uint32_t Mysql::Connection::getErrorNo()
|
|
{
|
|
return mysql_errno( m_pRawCon );
|
|
}
|
|
|
|
bool Mysql::Connection::ping()
|
|
{
|
|
return mysql_ping( m_pRawCon ) != 0;
|
|
}
|
|
|