MySQLConnection.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef HAVE_MYSQL
00023 #error MySQLConnection.h included, but HAVE_MYSQL not defined
00024 #endif
00025
00026 #ifdef HAVE_MYSQL
00027 #ifndef FIX_MYSQLCONNECTION_H
00028 #define FIX_MYSQLCONNECTION_H
00029
00030 #ifdef _MSC_VER
00031 #pragma warning( disable : 4503 4355 4786 4290 )
00032 #pragma comment( lib, "libMySQL" )
00033 #endif
00034
00035 #include <mysql.h>
00036 #include <errmsg.h>
00037 #include "DatabaseConnectionID.h"
00038 #include "DatabaseConnectionPool.h"
00039 #include "Mutex.h"
00040
00041 #undef MYSQL_PORT
00042
00043 namespace FIX
00044 {
00045 class MySQLQuery
00046 {
00047 public:
00048 MySQLQuery( const std::string& query )
00049 : m_result( 0 ), m_query( query )
00050 {}
00051
00052 ~MySQLQuery()
00053 {
00054 if( m_result )
00055 mysql_free_result( m_result );
00056 }
00057
00058 bool execute( MYSQL* pConnection )
00059 {
00060 int retry = 0;
00061
00062 do
00063 {
00064 if( m_result ) mysql_free_result( m_result );
00065 int errcode = mysql_query( pConnection, m_query.c_str() );
00066 m_result = mysql_store_result( pConnection );
00067 if( errcode == 0 )
00068 return true;
00069 m_status = mysql_errno( pConnection );
00070 m_reason = mysql_error( pConnection );
00071 mysql_ping( pConnection );
00072 retry++;
00073 } while( retry <= 1 );
00074 return success();
00075 }
00076
00077 bool success()
00078 {
00079 return m_status == 0;
00080 }
00081
00082 int rows()
00083 {
00084 return (int)mysql_num_rows( m_result );
00085 }
00086
00087 const std::string& reason()
00088 {
00089 return m_reason;
00090 }
00091
00092 char* getValue( int row, int column )
00093 {
00094 if( m_rows.empty() )
00095 {
00096 MYSQL_ROW row = 0;
00097 while( (row = mysql_fetch_row( m_result )) )
00098 m_rows.push_back(row);
00099 }
00100 return m_rows[row][column];
00101 }
00102
00103 void throwException() throw( IOException )
00104 {
00105 if( !success() )
00106 throw IOException( "Query failed [" + m_query + "] " + reason() );
00107 }
00108
00109 private:
00110 MYSQL_RES* m_result;
00111 int m_status;
00112 std::string m_query;
00113 std::string m_reason;
00114 std::vector<MYSQL_ROW> m_rows;
00115 };
00116
00117 class MySQLConnection
00118 {
00119 public:
00120 MySQLConnection
00121 ( const DatabaseConnectionID& id )
00122 : m_connectionID( id )
00123 {
00124 connect();
00125 }
00126
00127 MySQLConnection
00128 ( const std::string& database, const std::string& user,
00129 const std::string& password, const std::string& host, short port )
00130 : m_connectionID( database, user, password, host, port )
00131 {
00132 connect();
00133 }
00134
00135 ~MySQLConnection()
00136 {
00137 if( m_pConnection )
00138 mysql_close( m_pConnection );
00139 }
00140
00141 const DatabaseConnectionID& connectionID()
00142 {
00143 return m_connectionID;
00144 }
00145
00146 bool connected()
00147 {
00148 Locker locker( m_mutex );
00149 return mysql_ping( m_pConnection ) == 0;
00150 }
00151
00152 bool reconnect()
00153 {
00154 Locker locker( m_mutex );
00155 return mysql_ping( m_pConnection ) == 0;
00156 }
00157
00158 bool execute( MySQLQuery& pQuery )
00159 {
00160 Locker locker( m_mutex );
00161 return pQuery.execute( m_pConnection );
00162 }
00163
00164 private:
00165 void connect()
00166 {
00167 short port = m_connectionID.getPort();
00168 m_pConnection = mysql_init( NULL );
00169 if( !mysql_real_connect
00170 ( m_pConnection, m_connectionID.getHost().c_str(), m_connectionID.getUser().c_str(),
00171 m_connectionID.getPassword().c_str(), m_connectionID.getDatabase().c_str(), port, 0, 0 ) )
00172 {
00173 if( !connected() )
00174 throw ConfigError( std::string("Unable to connect to database [") + mysql_error(m_pConnection) + "]" );
00175 }
00176 #if( MYSQL_VERSION_ID > 50000 )
00177 my_bool reconnect = 1;
00178 mysql_options( m_pConnection, MYSQL_OPT_RECONNECT, static_cast<char*>(&reconnect) );
00179 #endif
00180 }
00181
00182 MYSQL* m_pConnection;
00183 DatabaseConnectionID m_connectionID;
00184 Mutex m_mutex;
00185 };
00186
00187 typedef DatabaseConnectionPool<MySQLConnection>
00188 MySQLConnectionPool;
00189 typedef std::auto_ptr< MySQLConnectionPool >
00190 MySQLConnectionPoolPtr;
00191 }
00192
00193 #endif //FIX_MYSQLCONNECTION_H
00194 #endif //HAVE_MYSQL