From 40bc05cf71af63efea62ca4b600f639e1ca4ed0c Mon Sep 17 00:00:00 2001 From: Mordred Date: Tue, 19 Sep 2017 00:02:14 +0200 Subject: [PATCH] First iteration of new mysql wrapper --- .../Server_Common/Database/Connection.cpp | 53 ++++ .../Server_Common/Database/Connection.h | 21 +- .../Server_Common/Database/MySqlBase.h | 4 +- .../Server_Common/Database/ResultSet.cpp | 274 ++++++++++++++++++ .../Server_Common/Database/ResultSet.h | 102 +++++++ .../Server_Common/Database/ResultSetBase.h | 70 +++++ .../Server_Common/Database/Statement.cpp | 66 +++++ .../Server_Common/Database/Statement.h | 56 ++++ .../Server_Common/Database/StatementBase.h | 36 +++ .../Server_Common/Database/mysql_util.cpp | 30 ++ .../Server_Common/Database/mysql_util.h | 110 +++++++ src/servers/Server_Zone/ServerZone.cpp | 33 ++- 12 files changed, 843 insertions(+), 12 deletions(-) create mode 100644 src/servers/Server_Common/Database/ResultSet.cpp create mode 100644 src/servers/Server_Common/Database/ResultSet.h create mode 100644 src/servers/Server_Common/Database/ResultSetBase.h create mode 100644 src/servers/Server_Common/Database/Statement.cpp create mode 100644 src/servers/Server_Common/Database/Statement.h create mode 100644 src/servers/Server_Common/Database/StatementBase.h create mode 100644 src/servers/Server_Common/Database/mysql_util.cpp create mode 100644 src/servers/Server_Common/Database/mysql_util.h diff --git a/src/servers/Server_Common/Database/Connection.cpp b/src/servers/Server_Common/Database/Connection.cpp index cb00a685..c59277c6 100644 --- a/src/servers/Server_Common/Database/Connection.cpp +++ b/src/servers/Server_Common/Database/Connection.cpp @@ -1,5 +1,9 @@ #include "Connection.h" #include "MySqlBase.h" +#include "Statement.h" + +#include +#include 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 ""; +} + diff --git a/src/servers/Server_Common/Database/Connection.h b/src/servers/Server_Common/Database/Connection.h index 15777ca3..1e7abfb7 100644 --- a/src/servers/Server_Common/Database/Connection.h +++ b/src/servers/Server_Common/Database/Connection.h @@ -6,6 +6,7 @@ #include #include + 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,7 +90,9 @@ namespace Db std::string getLastStatementInfo(); - private: + MYSQL * getRawCon(); + + private: MySqlBase * m_pBase; MYSQL * m_pRawCon; bool m_bConnected; diff --git a/src/servers/Server_Common/Database/MySqlBase.h b/src/servers/Server_Common/Database/MySqlBase.h index f759a014..b983b8c1 100644 --- a/src/servers/Server_Common/Database/MySqlBase.h +++ b/src/servers/Server_Common/Database/MySqlBase.h @@ -28,8 +28,8 @@ public: std::string getVersionInfo(); private: - MySqlBase(const MySqlBase &); - void operator=(MySqlBase &); + MySqlBase( const MySqlBase& ); + void operator=( MySqlBase& ); }; } diff --git a/src/servers/Server_Common/Database/ResultSet.cpp b/src/servers/Server_Common/Database/ResultSet.cpp new file mode 100644 index 00000000..92fc85b6 --- /dev/null +++ b/src/servers/Server_Common/Database/ResultSet.cpp @@ -0,0 +1,274 @@ +#include "ResultSet.h" +#include "Connection.h" +#include "Statement.h" +#include "mysql_util.h" +#include +#include +#include + +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 ) ); +} + diff --git a/src/servers/Server_Common/Database/ResultSet.h b/src/servers/Server_Common/Database/ResultSet.h new file mode 100644 index 00000000..f4cd339f --- /dev/null +++ b/src/servers/Server_Common/Database/ResultSet.h @@ -0,0 +1,102 @@ +#ifndef SAPPHIRE_RESULTSET_H +#define SAPPHIRE_RESULTSET_H + +#include +#include +#include + +#include "ResultSetBase.h" +#include + +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 diff --git a/src/servers/Server_Common/Database/ResultSetBase.h b/src/servers/Server_Common/Database/ResultSetBase.h new file mode 100644 index 00000000..50322ab6 --- /dev/null +++ b/src/servers/Server_Common/Database/ResultSetBase.h @@ -0,0 +1,70 @@ +#ifndef SAPPHIRE_RESULTSETBASE_H +#define SAPPHIRE_RESULTSETBASE_H + +#include +#include +#include + + +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 diff --git a/src/servers/Server_Common/Database/Statement.cpp b/src/servers/Server_Common/Database/Statement.cpp new file mode 100644 index 00000000..32855dfa --- /dev/null +++ b/src/servers/Server_Common/Database/Statement.cpp @@ -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 ); +} + diff --git a/src/servers/Server_Common/Database/Statement.h b/src/servers/Server_Common/Database/Statement.h new file mode 100644 index 00000000..df63676b --- /dev/null +++ b/src/servers/Server_Common/Database/Statement.h @@ -0,0 +1,56 @@ +#ifndef SAPPHIRE_STATEMENT_H +#define SAPPHIRE_STATEMENT_H + +#include +#include +#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 diff --git a/src/servers/Server_Common/Database/StatementBase.h b/src/servers/Server_Common/Database/StatementBase.h new file mode 100644 index 00000000..8397fee0 --- /dev/null +++ b/src/servers/Server_Common/Database/StatementBase.h @@ -0,0 +1,36 @@ +#ifndef SAPPHIRE_STATEMENTBASE_H +#define SAPPHIRE_STATEMENTBASE_H + +#include + +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 diff --git a/src/servers/Server_Common/Database/mysql_util.cpp b/src/servers/Server_Common/Database/mysql_util.cpp new file mode 100644 index 00000000..c73b04f3 --- /dev/null +++ b/src/servers/Server_Common/Database/mysql_util.cpp @@ -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; +} \ No newline at end of file diff --git a/src/servers/Server_Common/Database/mysql_util.h b/src/servers/Server_Common/Database/mysql_util.h new file mode 100644 index 00000000..f1de1eee --- /dev/null +++ b/src/servers/Server_Common/Database/mysql_util.h @@ -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 +, 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 +. + +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 +#include + +#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(0) + +#ifndef _WIN32 +# ifndef HAVE_FUNCTION_STRTOLL +# define strtoll(__a, __b, __c) static_cast(sql::mysql::util::strtold((__a), NULL)) +# define HAVE_FUNCTION_STRTOLL 1 +# endif +# ifndef HAVE_FUNCTION_STRTOULL +# define strtoull(__a, __b, __c) static_cast(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 diff --git a/src/servers/Server_Zone/ServerZone.cpp b/src/servers/Server_Zone/ServerZone.cpp index 0c5bb3df..132c142c 100644 --- a/src/servers/Server_Zone/ServerZone.cpp +++ b/src/servers/Server_Zone/ServerZone.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include @@ -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 )