2017-09-30 23:51:01 +02:00
|
|
|
#include "DbConnection.h"
|
|
|
|
#include "DbWorker.h"
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <MySqlConnector.h>
|
|
|
|
#include "Logging/Logger.h"
|
2018-03-09 00:06:44 +01:00
|
|
|
|
2017-09-30 23:51:01 +02:00
|
|
|
#include "PreparedStatement.h"
|
2018-03-09 00:06:44 +01:00
|
|
|
#include "Framework.h"
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) :
|
2018-08-29 21:40:59 +02:00
|
|
|
m_reconnecting( false ),
|
|
|
|
m_prepareError( false ),
|
|
|
|
m_queue( nullptr ),
|
|
|
|
m_pConnection( nullptr ),
|
|
|
|
m_connectionInfo( connInfo ),
|
|
|
|
m_connectionFlags( CONNECTION_SYNC )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Db::DbConnection::DbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* queue,
|
|
|
|
Sapphire::Db::ConnectionInfo& connInfo ) :
|
2018-08-29 21:40:59 +02:00
|
|
|
m_reconnecting( false ),
|
|
|
|
m_prepareError( false ),
|
|
|
|
m_queue( queue ),
|
|
|
|
m_pConnection( nullptr ),
|
|
|
|
m_connectionInfo( connInfo ),
|
|
|
|
m_connectionFlags( CONNECTION_ASYNC )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-10-24 12:53:26 +02:00
|
|
|
m_worker = std::make_shared< DbWorker >( m_queue, this );
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Db::DbConnection::~DbConnection()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
close();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::close()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_worker.reset();
|
|
|
|
m_stmts.clear();
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( m_pConnection )
|
|
|
|
{
|
|
|
|
m_pConnection->close();
|
|
|
|
m_pConnection.reset();
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::Db::DbConnection::open()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-10-24 12:53:26 +02:00
|
|
|
std::shared_ptr< Mysql::MySqlBase > base( new Mysql::MySqlBase() );
|
2018-08-29 21:40:59 +02:00
|
|
|
Mysql::optionMap options;
|
2018-10-26 23:07:55 +02:00
|
|
|
options[ Mysql::mysqlOption::MYSQL_OPT_RECONNECT ] = "1";
|
|
|
|
options[ Mysql::mysqlOption::MYSQL_SET_CHARSET_NAME ] = "utf8";
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
m_pConnection = base->connect( m_connectionInfo.host, m_connectionInfo.user, m_connectionInfo.password,
|
|
|
|
options, m_connectionInfo.port );
|
2017-10-07 23:10:13 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
m_pConnection->setSchema( m_connectionInfo.database );
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return 1;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return 0;
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
uint32_t Sapphire::Db::DbConnection::getLastError()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_pConnection->getErrorNo();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Db::DbConnection::ping()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_pConnection->ping();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Db::DbConnection::lockIfReady()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
return m_mutex.try_lock();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::unlock()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_mutex.unlock();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::beginTransaction()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_pConnection->beginTransaction();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::rollbackTransaction()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_pConnection->rollbackTransaction();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::commitTransaction()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_pConnection->commitTransaction();
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Db::DbConnection::execute( const std::string& sql )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
auto stmt = m_pConnection->createStatement();
|
|
|
|
bool result = stmt->execute( sql );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
std::shared_ptr< Mysql::ResultSet > Sapphire::Db::DbConnection::query( const std::string& sql )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
auto stmt = m_pConnection->createStatement();
|
|
|
|
auto result = stmt->executeQuery( sql );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-24 12:53:26 +02:00
|
|
|
std::shared_ptr< Mysql::ResultSet >
|
2018-11-29 16:55:48 +01:00
|
|
|
Sapphire::Db::DbConnection::query( std::shared_ptr< Sapphire::Db::PreparedStatement > stmt )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2018-10-24 12:53:26 +02:00
|
|
|
std::shared_ptr< Mysql::ResultSet > res( nullptr );
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !stmt )
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if( !ping() )
|
|
|
|
{
|
|
|
|
// naivly reconnect and hope for the best
|
|
|
|
open();
|
|
|
|
lockIfReady();
|
|
|
|
if( !prepareStatements() )
|
2017-09-30 23:51:01 +02:00
|
|
|
return nullptr;
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t index = stmt->getIndex();
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pStmt = getPreparedStatement( index );
|
2018-01-16 16:36:24 +01:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pStmt )
|
|
|
|
return nullptr;
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
stmt->setMysqlPS( pStmt );
|
|
|
|
try
|
|
|
|
{
|
|
|
|
stmt->bindParameters();
|
|
|
|
return pStmt->executeQuery();
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Db::DbConnection::execute( std::shared_ptr< Sapphire::Db::PreparedStatement > stmt )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !stmt )
|
|
|
|
return false;
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
uint32_t index = stmt->getIndex();
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
auto pStmt = getPreparedStatement( index );
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
if( !pStmt )
|
|
|
|
return false;
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
stmt->setMysqlPS( pStmt );
|
|
|
|
try
|
|
|
|
{
|
|
|
|
stmt->bindParameters();
|
|
|
|
return pStmt->execute();
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
return false;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
std::shared_ptr< Mysql::PreparedStatement > Sapphire::Db::DbConnection::getPreparedStatement( uint32_t index )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
assert( index < m_stmts.size() );
|
|
|
|
auto ret = m_stmts[ index ];
|
|
|
|
if( !ret )
|
2018-09-26 03:32:43 -04:00
|
|
|
return nullptr;
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
return ret;
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
void Sapphire::Db::DbConnection::prepareStatement( uint32_t index, const std::string& sql, Sapphire::Db::ConnectionFlags flags )
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
m_queries.insert( PreparedStatementMap::value_type( index, std::make_pair( sql, flags ) ) );
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
// Check if specified query should be prepared on this connection
|
|
|
|
// i.e. don't prepare async statements on synchronous connections
|
|
|
|
// to save memory that will not be used.
|
|
|
|
if( !( m_connectionFlags & flags ) )
|
|
|
|
{
|
|
|
|
m_stmts[ index ].reset();
|
|
|
|
return;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-10-24 12:53:26 +02:00
|
|
|
std::shared_ptr< Mysql::PreparedStatement > pStmt( nullptr );
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-08-29 21:40:59 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
pStmt = m_pConnection->prepareStatement( sql );
|
|
|
|
}
|
|
|
|
catch( std::runtime_error& e )
|
|
|
|
{
|
2018-12-23 03:53:08 +01:00
|
|
|
Logger::error( e.what() );
|
2018-08-29 21:40:59 +02:00
|
|
|
m_prepareError = true;
|
|
|
|
}
|
2017-09-30 23:51:01 +02:00
|
|
|
|
2018-10-24 12:53:26 +02:00
|
|
|
m_stmts[ index ] = std::shared_ptr< Mysql::PreparedStatement >( pStmt );
|
2017-09-30 23:51:01 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
bool Sapphire::Db::DbConnection::prepareStatements()
|
2017-09-30 23:51:01 +02:00
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
doPrepareStatements();
|
|
|
|
return !m_prepareError;
|
2017-09-30 23:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|