mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 14:37:44 +00:00
First iteration of new mysql wrapper
This commit is contained in:
parent
b97162ba5d
commit
1faa3c3898
12 changed files with 843 additions and 12 deletions
|
@ -1,5 +1,9 @@
|
|||
#include "Connection.h"
|
||||
#include "MySqlBase.h"
|
||||
#include "Statement.h"
|
||||
|
||||
#include <vector>
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
Core::Db::Connection::Connection( MySqlBase * pBase,
|
||||
const std::string& hostName,
|
||||
|
@ -174,3 +178,52 @@ bool Core::Db::Connection::getAutoCommit()
|
|||
return ac != 0;
|
||||
}
|
||||
|
||||
void Core::Db::Connection::beginTransaction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Core::Db::Connection::commitTransaction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Core::Db::Connection::rollbackTransaction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string Core::Db::Connection::escapeString( const std::string &inData )
|
||||
{
|
||||
boost::scoped_array< 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 Core::Db::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 );
|
||||
}
|
||||
|
||||
Core::Db::Statement *Core::Db::Connection::createStatement()
|
||||
{
|
||||
return new Statement( this );
|
||||
}
|
||||
|
||||
MYSQL *Core::Db::Connection::getRawCon()
|
||||
{
|
||||
return m_pRawCon;
|
||||
}
|
||||
|
||||
std::string Core::Db::Connection::getError()
|
||||
{
|
||||
auto mysqlError = mysql_error( m_pRawCon );
|
||||
if( mysqlError )
|
||||
return std::string( mysqlError );
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <mysql.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Db
|
||||
|
@ -13,6 +14,7 @@ namespace Db
|
|||
|
||||
typedef std::map< enum mysql_option, std::string > optionMap;
|
||||
class MySqlBase;
|
||||
class Statement;
|
||||
|
||||
class Connection
|
||||
{
|
||||
|
@ -45,28 +47,27 @@ namespace Db
|
|||
void setAutoCommit( bool autoCommit );
|
||||
bool getAutoCommit();
|
||||
|
||||
std::string escapeString( const std::string& inData );
|
||||
|
||||
void setSchema( const std::string& catalog );
|
||||
|
||||
Statement * createStatement();
|
||||
|
||||
//// implemented up to this point
|
||||
|
||||
void beginTransaction();
|
||||
void commitTransaction();
|
||||
void rollbackTransaction();
|
||||
|
||||
//Statement * createStatement();
|
||||
|
||||
std::string escapeString( const std::string& );
|
||||
|
||||
std::string getSchema();
|
||||
void setSchema( const std::string& catalog );
|
||||
|
||||
void getOption( enum mysql_option option, void * optionValue );
|
||||
|
||||
std::string getOption( enum mysql_option option );
|
||||
|
||||
//DatabaseMetaData * getMetaData();
|
||||
|
||||
//enum_transaction_isolation getTransactionIsolation();
|
||||
|
||||
//const SQLWarning * getWarnings();
|
||||
std::string getError();
|
||||
|
||||
bool isReadOnly();
|
||||
void setReadOnly( bool readOnly );
|
||||
|
@ -89,6 +90,8 @@ namespace Db
|
|||
|
||||
std::string getLastStatementInfo();
|
||||
|
||||
MYSQL * getRawCon();
|
||||
|
||||
private:
|
||||
MySqlBase * m_pBase;
|
||||
MYSQL * m_pRawCon;
|
||||
|
|
274
src/servers/Server_Common/Database/ResultSet.cpp
Normal file
274
src/servers/Server_Common/Database/ResultSet.cpp
Normal file
|
@ -0,0 +1,274 @@
|
|||
#include "ResultSet.h"
|
||||
#include "Connection.h"
|
||||
#include "Statement.h"
|
||||
#include "mysql_util.h"
|
||||
#include <cctype>
|
||||
#include <clocale>
|
||||
#include <vector>
|
||||
|
||||
Core::Db::ResultSet::ResultSet( MYSQL_RES *res, Core::Db::Statement *par )
|
||||
{
|
||||
m_pRes = res;
|
||||
m_numRows = mysql_num_rows( res );
|
||||
m_numFields = mysql_num_fields( res );
|
||||
m_pStmt = par;
|
||||
m_rowPosition = 1;
|
||||
|
||||
for (unsigned int i = 0; i < m_numFields; ++i)
|
||||
{
|
||||
|
||||
std::string fieldName( getFieldMeta(i + 1)->name );
|
||||
|
||||
std::transform( fieldName.begin(), fieldName.end(), fieldName.begin(),
|
||||
[](unsigned char c){ return std::toupper(c); } );
|
||||
|
||||
m_fieldNameToIndex[fieldName] = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Core::Db::ResultSet::~ResultSet()
|
||||
{
|
||||
mysql_free_result( m_pRes );
|
||||
}
|
||||
|
||||
MYSQL_FIELD* Core::Db::ResultSet::getFieldMeta( unsigned int columnIndex ) const
|
||||
{
|
||||
return mysql_fetch_field_direct( m_pRes, columnIndex - 1 );
|
||||
}
|
||||
|
||||
uint32_t Core::Db::ResultSet::findColumn( const std::string &columnLabel ) const
|
||||
{
|
||||
std::string searchColumn = columnLabel;
|
||||
|
||||
std::transform( searchColumn.begin(), searchColumn.end(), searchColumn.begin(),
|
||||
[](unsigned char c){ return std::toupper(c); } );
|
||||
|
||||
auto iter = m_fieldNameToIndex.find( searchColumn );
|
||||
if( iter == m_fieldNameToIndex.end() )
|
||||
return 0;
|
||||
|
||||
return iter->second + 1;
|
||||
}
|
||||
|
||||
size_t Core::Db::ResultSet::getRow() const
|
||||
{
|
||||
return static_cast< size_t >( m_rowPosition );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::isLast() const
|
||||
{
|
||||
return ( m_rowPosition == m_numRows );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::isFirst() const
|
||||
{
|
||||
return ( m_rowPosition == 1 );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::next()
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
m_lastQueriedColumn = -1;
|
||||
m_row = mysql_fetch_row( m_pRes );
|
||||
if( m_row == nullptr )
|
||||
{
|
||||
if( m_pStmt->errNo() == 2013 || m_pStmt->errNo() == 2000 )
|
||||
throw std::runtime_error( "Error fetching next row " + std::to_string( m_pStmt->errNo() ) +
|
||||
": " + m_pStmt->getConnection()->getError() );
|
||||
}
|
||||
if( ( ret = ( m_row != nullptr ) ) )
|
||||
++m_rowPosition;
|
||||
else
|
||||
m_rowPosition = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t Core::Db::ResultSet::rowsCount() const
|
||||
{
|
||||
return static_cast< uint32_t >( m_numRows );
|
||||
}
|
||||
|
||||
const Core::Db::Statement *Core::Db::ResultSet::getStatement() const
|
||||
{
|
||||
return m_pStmt;
|
||||
}
|
||||
|
||||
int64_t Core::Db::ResultSet::getInt64( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getInt64: invalid value of 'columnIndex'" );
|
||||
|
||||
m_lastQueriedColumn = columnIndex;
|
||||
|
||||
if( m_row[columnIndex - 1] == nullptr )
|
||||
{
|
||||
m_wasNull = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_wasNull = false;
|
||||
if( getFieldMeta(columnIndex)->type == MYSQL_TYPE_BIT &&
|
||||
getFieldMeta(columnIndex)->flags != ( BINARY_FLAG | UNSIGNED_FLAG ) )
|
||||
{
|
||||
uint64_t uval = 0;
|
||||
std::div_t length = std::div( getFieldMeta( columnIndex )->length, 8 );
|
||||
if( length.rem != 0 )
|
||||
++length.quot;
|
||||
|
||||
switch( length.quot )
|
||||
{
|
||||
case 8:uval = (uint64_t) bit_uint8korr( m_row[columnIndex - 1] );break;
|
||||
case 7:uval = (uint64_t) bit_uint7korr( m_row[columnIndex - 1] );break;
|
||||
case 6:uval = (uint64_t) bit_uint6korr( m_row[columnIndex - 1] );break;
|
||||
case 5:uval = (uint64_t) bit_uint5korr( m_row[columnIndex - 1] );break;
|
||||
case 4:uval = (uint64_t) bit_uint4korr( m_row[columnIndex - 1] );break;
|
||||
case 3:uval = (uint64_t) bit_uint3korr( m_row[columnIndex - 1] );break;
|
||||
case 2:uval = (uint64_t) bit_uint2korr( m_row[columnIndex - 1] );break;
|
||||
case 1:uval = (uint64_t) bit_uint1korr( m_row[columnIndex - 1] );break;
|
||||
}
|
||||
return uval;
|
||||
}
|
||||
|
||||
if( getFieldMeta( columnIndex)->flags & UNSIGNED_FLAG )
|
||||
return strtoull( m_row[columnIndex - 1], nullptr, 10 );
|
||||
return strtoll( m_row[columnIndex - 1], nullptr, 10 );
|
||||
}
|
||||
|
||||
int64_t Core::Db::ResultSet::getInt64( const std::string &columnLabel ) const
|
||||
{
|
||||
return getInt64( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
uint64_t Core::Db::ResultSet::getUInt64( uint32_t columnIndex ) const
|
||||
{
|
||||
return static_cast< uint64_t >( getInt64( columnIndex ) );
|
||||
}
|
||||
|
||||
uint64_t Core::Db::ResultSet::getUInt64( const std::string &columnLabel ) const
|
||||
{
|
||||
return getUInt64( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
int32_t Core::Db::ResultSet::getInt( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getInt: invalid value of 'columnIndex'" );
|
||||
|
||||
if( ( getFieldMeta( columnIndex )->flags & UNSIGNED_FLAG ) != 0 )
|
||||
return static_cast< uint32_t >( getInt64( columnIndex ) );
|
||||
|
||||
return static_cast< int32_t >( getInt64( columnIndex ) );
|
||||
}
|
||||
|
||||
int32_t Core::Db::ResultSet::getInt( const std::string &columnLabel ) const
|
||||
{
|
||||
return getInt( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
uint32_t Core::Db::ResultSet::getUInt( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getUInt: invalid value of 'columnIndex'" );
|
||||
|
||||
return static_cast< uint32_t >( getUInt64( columnIndex ) );
|
||||
}
|
||||
|
||||
uint32_t Core::Db::ResultSet::getUInt( const std::string &columnLabel ) const
|
||||
{
|
||||
return getUInt( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
long double Core::Db::ResultSet::getDouble( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getDouble: invalid value of 'columnIndex'" );
|
||||
|
||||
m_lastQueriedColumn = columnIndex;
|
||||
|
||||
if( m_row[columnIndex - 1] == nullptr )
|
||||
{
|
||||
m_wasNull = true;
|
||||
return 0.0;
|
||||
}
|
||||
m_wasNull = false;
|
||||
if( getFieldMeta(columnIndex)->type == MYSQL_TYPE_BIT )
|
||||
return static_cast< long double >( getInt64( columnIndex ) );
|
||||
|
||||
return strtonum( m_row[columnIndex - 1] );
|
||||
}
|
||||
|
||||
long double Core::Db::ResultSet::getDouble( const std::string &columnLabel ) const
|
||||
{
|
||||
return getDouble( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::getBoolean( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getBoolean: invalid value of 'columnIndex'" );
|
||||
|
||||
return getInt( columnIndex ) ? true : false;
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::getBoolean( const std::string &columnLabel ) const
|
||||
{
|
||||
return getInt( columnLabel ) ? true : false;
|
||||
}
|
||||
|
||||
std::string Core::Db::ResultSet::getString( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getString: invalid value of 'columnIndex'" );
|
||||
|
||||
if( m_row == nullptr || m_row[columnIndex - 1] == nullptr )
|
||||
{
|
||||
m_wasNull = true;
|
||||
return "";
|
||||
}
|
||||
|
||||
if( getFieldMeta( columnIndex )->type == MYSQL_TYPE_BIT )
|
||||
{
|
||||
char buf[30];
|
||||
snprintf( buf, sizeof( buf ) - 1, "%llu", ( unsigned long long ) getUInt64( columnIndex ) );
|
||||
return std::string( buf );
|
||||
}
|
||||
|
||||
size_t len = mysql_fetch_lengths( m_pRes )[columnIndex - 1];
|
||||
m_wasNull = false;
|
||||
return std::string( m_row[columnIndex - 1], len );
|
||||
}
|
||||
|
||||
std::string Core::Db::ResultSet::getString( const std::string &columnLabel ) const
|
||||
{
|
||||
return getString( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::isNull( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::isNull: invalid value of 'columnIndex'" );
|
||||
|
||||
return ( m_row[columnIndex - 1] == nullptr );
|
||||
}
|
||||
|
||||
bool Core::Db::ResultSet::isNull( const std::string &columnLabel ) const
|
||||
{
|
||||
return isNull( findColumn( columnLabel ) );
|
||||
}
|
||||
|
||||
std::istream* Core::Db::ResultSet::getBlob( uint32_t columnIndex ) const
|
||||
{
|
||||
if( columnIndex == 0 || columnIndex > m_numFields )
|
||||
throw std::runtime_error( "ResultSet::getBlob: invalid value of 'columnIndex'" );
|
||||
|
||||
return new std::istringstream( getString( columnIndex ) );
|
||||
}
|
||||
|
||||
std::istream* Core::Db::ResultSet::getBlob( const std::string& columnLabel ) const
|
||||
{
|
||||
return new std::istringstream( getString( columnLabel ) );
|
||||
}
|
||||
|
102
src/servers/Server_Common/Database/ResultSet.h
Normal file
102
src/servers/Server_Common/Database/ResultSet.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
#ifndef SAPPHIRE_RESULTSET_H
|
||||
#define SAPPHIRE_RESULTSET_H
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
#include "ResultSetBase.h"
|
||||
#include <mysql.h>
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Db
|
||||
{
|
||||
|
||||
class Statement;
|
||||
//class ResultSetMetaData;
|
||||
|
||||
|
||||
class ResultSet : public ResultSetBase
|
||||
{
|
||||
MYSQL_ROW m_row;
|
||||
|
||||
uint32_t m_numFields;
|
||||
uint64_t m_numRows;
|
||||
uint64_t m_rowPosition;
|
||||
|
||||
typedef std::map< std::string, uint32_t > FieldNameIndexMap;
|
||||
|
||||
FieldNameIndexMap m_fieldNameToIndex;
|
||||
|
||||
mutable bool m_wasNull;
|
||||
|
||||
mutable uint32_t m_lastQueriedColumn;
|
||||
|
||||
Statement* m_pStmt;
|
||||
|
||||
MYSQL_RES* m_pRes;
|
||||
|
||||
//boost::scoped_ptr< MySQL_ResultSetMetaData > rs_meta;
|
||||
|
||||
protected:
|
||||
MYSQL_FIELD* getFieldMeta( unsigned int columnIndex ) const;
|
||||
|
||||
public:
|
||||
ResultSet( MYSQL_RES* res, Statement* par );
|
||||
|
||||
virtual ~ResultSet();
|
||||
|
||||
uint32_t findColumn( const std::string& columnLabel ) const;
|
||||
|
||||
std::istream * getBlob( uint32_t columnIndex ) const;
|
||||
std::istream * getBlob( const std::string& columnLabel ) const;
|
||||
|
||||
bool getBoolean( uint32_t columnIndex ) const;
|
||||
bool getBoolean( const std::string& columnLabel ) const;
|
||||
|
||||
long double getDouble( uint32_t columnIndex ) const;
|
||||
long double getDouble( const std::string& columnLabel ) const;
|
||||
|
||||
int32_t getInt( uint32_t columnIndex ) const;
|
||||
int32_t getInt( const std::string& columnLabel ) const;
|
||||
|
||||
uint32_t getUInt( uint32_t columnIndex ) const;
|
||||
uint32_t getUInt( const std::string& columnLabel ) const;
|
||||
|
||||
int64_t getInt64( uint32_t columnIndex ) const;
|
||||
int64_t getInt64( const std::string& columnLabel ) const;
|
||||
|
||||
uint64_t getUInt64( uint32_t columnIndex ) const;
|
||||
uint64_t getUInt64( const std::string& columnLabel ) const;
|
||||
|
||||
//sql::ResultSetMetaData * getMetaData() const;
|
||||
|
||||
size_t getRow() const;
|
||||
|
||||
const Statement * getStatement() const;
|
||||
|
||||
std::string getString( uint32_t columnIndex ) const;
|
||||
std::string getString( const std::string& columnLabel ) const;
|
||||
|
||||
bool isFirst() const;
|
||||
|
||||
bool isLast() const;
|
||||
|
||||
bool isNull( uint32_t columnIndex ) const;
|
||||
|
||||
bool isNull( const std::string& columnLabel ) const;
|
||||
|
||||
bool next();
|
||||
|
||||
size_t rowsCount() const;
|
||||
private:
|
||||
ResultSet( const ResultSet& );
|
||||
void operator=( ResultSet& );
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //SAPPHIRE_RESULTSET_H
|
70
src/servers/Server_Common/Database/ResultSetBase.h
Normal file
70
src/servers/Server_Common/Database/ResultSetBase.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#ifndef SAPPHIRE_RESULTSETBASE_H
|
||||
#define SAPPHIRE_RESULTSETBASE_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Db
|
||||
{
|
||||
|
||||
class Statement;
|
||||
|
||||
class ResultSetBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ResultSetBase() {}
|
||||
|
||||
virtual uint32_t findColumn( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual std::istream *getBlob( uint32_t columnIndex ) const = 0;
|
||||
virtual std::istream *getBlob( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual bool getBoolean( uint32_t columnIndex ) const = 0;
|
||||
virtual bool getBoolean( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual long double getDouble( uint32_t columnIndex ) const = 0;
|
||||
virtual long double getDouble( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual int32_t getInt( uint32_t columnIndex ) const = 0;
|
||||
virtual int32_t getInt( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual uint32_t getUInt( uint32_t columnIndex ) const = 0;
|
||||
virtual uint32_t getUInt( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual int64_t getInt64( uint32_t columnIndex ) const = 0;
|
||||
virtual int64_t getInt64( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual uint64_t getUInt64( uint32_t columnIndex ) const = 0;
|
||||
virtual uint64_t getUInt64( const std::string &columnLabel ) const = 0;
|
||||
|
||||
//virtual ResultSetMetaData *getMetaData() const = 0;
|
||||
|
||||
virtual size_t getRow() const = 0;
|
||||
|
||||
virtual const Statement *getStatement() const = 0;
|
||||
|
||||
virtual std::string getString( uint32_t columnIndex ) const = 0;
|
||||
virtual std::string getString( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual bool isFirst() const = 0;
|
||||
|
||||
virtual bool isLast() const = 0;
|
||||
|
||||
virtual bool isNull( uint32_t columnIndex ) const = 0;
|
||||
|
||||
virtual bool isNull( const std::string &columnLabel ) const = 0;
|
||||
|
||||
virtual bool next() = 0;
|
||||
|
||||
virtual size_t rowsCount() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //SAPPHIRE_RESULTSETBASE_H
|
66
src/servers/Server_Common/Database/Statement.cpp
Normal file
66
src/servers/Server_Common/Database/Statement.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "Statement.h"
|
||||
#include "Connection.h"
|
||||
#include "ResultSet.h"
|
||||
#include "mysql_util.h"
|
||||
|
||||
Core::Db::Connection* Core::Db::Statement::getConnection()
|
||||
{
|
||||
return m_pConnection;
|
||||
}
|
||||
|
||||
Core::Db::Statement::Statement( Core::Db::Connection *conn ) :
|
||||
m_pConnection( conn )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Core::Db::Statement::doQuery( const std::string &q )
|
||||
{
|
||||
mysql_real_query( m_pConnection->getRawCon(), q.c_str(), q.length() );
|
||||
|
||||
if( errNo() )
|
||||
throw std::runtime_error( m_pConnection->getError() );
|
||||
|
||||
m_warningsCount = getWarningCount();
|
||||
}
|
||||
|
||||
bool Core::Db::Statement::execute( const std::string &sql )
|
||||
{
|
||||
doQuery( sql );
|
||||
bool ret = mysql_field_count( m_pConnection->getRawCon() ) == 0;
|
||||
m_lastUpdateCount = mysql_affected_rows( m_pConnection->getRawCon() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t Core::Db::Statement::getUpdateCount()
|
||||
{
|
||||
return m_lastUpdateCount;
|
||||
}
|
||||
|
||||
uint32_t Core::Db::Statement::getWarningCount()
|
||||
{
|
||||
return mysql_warning_count( m_pConnection->getRawCon() );
|
||||
}
|
||||
|
||||
uint32_t Core::Db::Statement::errNo()
|
||||
{
|
||||
return mysql_errno( m_pConnection->getRawCon() );
|
||||
}
|
||||
|
||||
Core::Db::ResultSet* Core::Db::Statement::executeQuery( const std::string &sql )
|
||||
{
|
||||
m_lastUpdateCount = UL64(~0);
|
||||
doQuery( sql );
|
||||
|
||||
return new ResultSet( mysql_store_result( m_pConnection->getRawCon() ), this );
|
||||
}
|
||||
|
||||
Core::Db::ResultSet *Core::Db::Statement::getResultSet()
|
||||
{
|
||||
if( errNo() != 0 )
|
||||
throw std::runtime_error( "Error during getResultSet() : " + std::to_string( errNo() ) + ": " +
|
||||
m_pConnection->getError() );
|
||||
|
||||
return new ResultSet( mysql_store_result( m_pConnection->getRawCon() ), this );
|
||||
}
|
||||
|
56
src/servers/Server_Common/Database/Statement.h
Normal file
56
src/servers/Server_Common/Database/Statement.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef SAPPHIRE_STATEMENT_H
|
||||
#define SAPPHIRE_STATEMENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "StatementBase.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Db
|
||||
{
|
||||
class Connection;
|
||||
class ResultSet;
|
||||
|
||||
class Statement : public StatementBase
|
||||
{
|
||||
protected:
|
||||
Connection * m_pConnection;
|
||||
|
||||
void doQuery( const std::string& q );
|
||||
|
||||
uint64_t m_lastUpdateCount;
|
||||
|
||||
unsigned int m_warningsCount;
|
||||
|
||||
public:
|
||||
Statement( Connection* conn );
|
||||
|
||||
virtual ~Statement() {};
|
||||
|
||||
Connection * getConnection() override;
|
||||
|
||||
bool execute( const std::string& sql ) override;
|
||||
|
||||
ResultSet * executeQuery( const std::string& sql ) override;
|
||||
|
||||
ResultSet * getResultSet() override;
|
||||
|
||||
uint64_t getUpdateCount() override;
|
||||
|
||||
uint32_t getWarningCount() override;
|
||||
|
||||
uint32_t errNo() override;
|
||||
|
||||
private:
|
||||
/* Prevent use of these */
|
||||
Statement( const Statement& );
|
||||
void operator=( Statement& );
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //SAPPHIRE_STATEMENT_H
|
36
src/servers/Server_Common/Database/StatementBase.h
Normal file
36
src/servers/Server_Common/Database/StatementBase.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef SAPPHIRE_STATEMENTBASE_H
|
||||
#define SAPPHIRE_STATEMENTBASE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Db
|
||||
{
|
||||
|
||||
class Connection;
|
||||
class ResultSet;
|
||||
|
||||
class StatementBase
|
||||
{
|
||||
public:
|
||||
virtual ~StatementBase() {};
|
||||
|
||||
virtual Connection* getConnection() = 0;
|
||||
|
||||
virtual bool execute( const std::string& sql ) = 0;
|
||||
|
||||
virtual ResultSet* executeQuery( const std::string& sql ) = 0;
|
||||
|
||||
virtual ResultSet* getResultSet() = 0;
|
||||
|
||||
virtual uint64_t getUpdateCount() = 0;
|
||||
|
||||
virtual uint32_t getWarningCount() = 0;
|
||||
|
||||
virtual uint32_t errNo() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SAPPHIRE_STATEMENTBASE_H
|
30
src/servers/Server_Common/Database/mysql_util.cpp
Normal file
30
src/servers/Server_Common/Database/mysql_util.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "mysql_util.h"
|
||||
|
||||
long double strtonum( const std::string &str, int radix )
|
||||
{
|
||||
typedef std::istreambuf_iterator< char > iter_t;
|
||||
static std::locale c_locale( "C" );
|
||||
static const std::num_get< char > &cvt = std::use_facet< std::num_get< char > >( c_locale );
|
||||
|
||||
std::istringstream inp( str );
|
||||
long double val = 0.0L;
|
||||
|
||||
inp.imbue( c_locale );
|
||||
|
||||
switch( radix )
|
||||
{
|
||||
case 10: inp.setf( std::ios_base::dec, std::ios_base::basefield ); break;
|
||||
case 16: inp.setf( std::ios_base::hex, std::ios_base::basefield ); break;
|
||||
case 8: inp.setf( std::ios_base::oct, std::ios_base::basefield ); break;
|
||||
default:
|
||||
inp.setf( std::ios_base::fmtflags( 0 ), std::ios_base::basefield );
|
||||
break;
|
||||
}
|
||||
|
||||
iter_t beg( inp ), end;
|
||||
std::ios::iostate err = std::ios_base::goodbit;
|
||||
|
||||
cvt.get( beg, end, inp, err, val );
|
||||
|
||||
return val;
|
||||
}
|
110
src/servers/Server_Common/Database/mysql_util.h
Normal file
110
src/servers/Server_Common/Database/mysql_util.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
The MySQL Connector/C++ is licensed under the terms of the GPLv2
|
||||
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
||||
MySQL Connectors. There are special exceptions to the terms and
|
||||
conditions of the GPLv2 as it is applied to this software, see the
|
||||
FLOSS License Exception
|
||||
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SAPPHIRE_MYSQL_UTIL_H
|
||||
#define SAPPHIRE_MYSQL_UTIL_H
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef UL64
|
||||
#ifdef _WIN32
|
||||
#define UL64(x) x##ui64
|
||||
#else
|
||||
#define UL64(x) x##ULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef L64
|
||||
#ifdef _WIN32
|
||||
#define L64(x) x##i64
|
||||
#else
|
||||
#define L64(x) x##LL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NULLCSTR static_cast<char *>(0)
|
||||
|
||||
#ifndef _WIN32
|
||||
# ifndef HAVE_FUNCTION_STRTOLL
|
||||
# define strtoll(__a, __b, __c) static_cast<long long>(sql::mysql::util::strtold((__a), NULL))
|
||||
# define HAVE_FUNCTION_STRTOLL 1
|
||||
# endif
|
||||
# ifndef HAVE_FUNCTION_STRTOULL
|
||||
# define strtoull(__a, __b, __c) static_cast<unsigned long long>(sql::mysql::util::strtold((__a), NULL))
|
||||
# define HAVE_FUNCTION_STRTOULL 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef strtoll
|
||||
# define strtoll(x, e, b) _strtoi64((x), (e), (b))
|
||||
# endif
|
||||
# ifndef strtoull
|
||||
# define strtoull(x, e, b) _strtoui64((x), (e), (b))
|
||||
# endif
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#define bit_uint1korr(A) (*(((uint8_t*)(A))))
|
||||
|
||||
#define bit_uint2korr(A) ((uint16_t) (((uint16_t) (((unsigned char*) (A))[1])) +\
|
||||
((uint16_t) (((unsigned char*) (A))[0]) << 8)))
|
||||
#define bit_uint3korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[0])) << 16)))
|
||||
#define bit_uint4korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[0])) << 24)))
|
||||
#define bit_uint5korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[4])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[3])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[2])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[1])) << 24)) +\
|
||||
(((uint64_t) (((unsigned char*) (A))[0])) << 32))
|
||||
#define bit_uint6korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[5])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[4])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[3])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[2])) << 24)) +\
|
||||
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[1])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[0]) << 8)))) <<\
|
||||
32))
|
||||
#define bit_uint7korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[6])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[5])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[4])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[3])) << 24)) +\
|
||||
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[0])) << 16))) <<\
|
||||
32))
|
||||
#define bit_uint8korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[7])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[6])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[5])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[4])) << 24)) +\
|
||||
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
|
||||
(((uint32_t) (((unsigned char*) (A))[0])) << 24))) <<\
|
||||
32))
|
||||
|
||||
long double strtonum( const std::string &str, int radix = 10);
|
||||
#endif //SAPPHIRE_MYSQL_UTIL_H
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include <src/servers/Server_Common/Database/MySqlBase.h>
|
||||
#include <src/servers/Server_Common/Database/Connection.h>
|
||||
#include <src/servers/Server_Common/Database/Statement.h>
|
||||
#include <src/servers/Server_Common/Database/ResultSet.h>
|
||||
|
||||
#include <src/servers/Server_Common/Network/Connection.h>
|
||||
#include <src/servers/Server_Common/Network/Hive.h>
|
||||
|
@ -160,13 +162,14 @@ bool Core::ServerZone::loadSettings( int32_t argc, char* argv[] )
|
|||
|
||||
try
|
||||
{
|
||||
// bunch of test cases for db wrapper
|
||||
Core::Db::MySqlBase base;
|
||||
g_log.info( base.getVersionInfo() );
|
||||
|
||||
Core::Db::optionMap options;
|
||||
options[ MYSQL_OPT_RECONNECT ] = "1";
|
||||
|
||||
auto con = base.connect( "127.0.0.1", "root", "", options );
|
||||
boost::scoped_ptr< Core::Db::Connection > con( base.connect( "127.0.0.1", "root", "", options ) );
|
||||
|
||||
if( con->getAutoCommit() )
|
||||
g_log.info( "autocommit active" );
|
||||
|
@ -181,6 +184,34 @@ bool Core::ServerZone::loadSettings( int32_t argc, char* argv[] )
|
|||
if( con->getAutoCommit() )
|
||||
g_log.info( "autocommit active" );
|
||||
|
||||
con->setSchema( "sapphire" );
|
||||
|
||||
boost::scoped_ptr< Core::Db::Statement > stmt( con->createStatement() );
|
||||
bool t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" );
|
||||
// t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" ); // throws duplicate entry
|
||||
t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" );
|
||||
//t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
|
||||
//boost::scoped_ptr< Core::Db::Statement > stmt1( con->createStatement() );
|
||||
//bool t2 = stmt1->execute( "INSERT INTO BLARGH!" ); // throws error
|
||||
|
||||
boost::scoped_ptr< Core::Db::Statement > stmt2( con->createStatement() );
|
||||
boost::scoped_ptr< Core::Db::ResultSet > res( stmt2->executeQuery( "SELECT id,ip,port FROM zoneservers" ) );
|
||||
|
||||
while( res->next() )
|
||||
{
|
||||
g_log.info( "id: " + std::to_string( res->getUInt( "id" ) ) );
|
||||
g_log.info( "ip: " + res->getString( "ip" ) );
|
||||
g_log.info( "port: " + std::to_string( res->getUInt( "port" ) ) );
|
||||
|
||||
// alternatively ( slightly faster )
|
||||
// g_log.info( "id: " + std::to_string( res->getUInt( 1 ) ) );
|
||||
// g_log.info( "ip: " + res->getString( 2 ) );
|
||||
// g_log.info( "port: " + std::to_string( res->getUInt( 3 ) ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch( std::runtime_error e )
|
||||
|
|
Loading…
Add table
Reference in a new issue