MySQLConnection.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* -*- C++ -*- */
  2. /****************************************************************************
  3. ** Copyright (c) 2001-2014
  4. **
  5. ** This file is part of the QuickFIX FIX Engine
  6. **
  7. ** This file may be distributed under the terms of the quickfixengine.org
  8. ** license as defined by quickfixengine.org and appearing in the file
  9. ** LICENSE included in the packaging of this file.
  10. **
  11. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  12. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. **
  14. ** See http://www.quickfixengine.org/LICENSE for licensing information.
  15. **
  16. ** Contact ask@quickfixengine.org if any conditions of this licensing are
  17. ** not clear to you.
  18. **
  19. ****************************************************************************/
  20. #ifndef HAVE_MYSQL
  21. #error MySQLConnection.h included, but HAVE_MYSQL not defined
  22. #endif
  23. #ifdef HAVE_MYSQL
  24. #ifndef FIX_MYSQLCONNECTION_H
  25. #define FIX_MYSQLCONNECTION_H
  26. #ifdef _MSC_VER
  27. #pragma warning( disable : 4503 4355 4786 4290 )
  28. #pragma comment( lib, "libMySQL" )
  29. #endif
  30. #include <mysql.h>
  31. #include <errmsg.h>
  32. #include "DatabaseConnectionID.h"
  33. #include "DatabaseConnectionPool.h"
  34. #include "Mutex.h"
  35. #undef MYSQL_PORT
  36. namespace FIX
  37. {
  38. class MySQLQuery
  39. {
  40. public:
  41. MySQLQuery( const std::string& query )
  42. : m_result( 0 ), m_query( query )
  43. {}
  44. ~MySQLQuery()
  45. {
  46. if( m_result )
  47. mysql_free_result( m_result );
  48. }
  49. bool execute( MYSQL* pConnection )
  50. {
  51. int retry = 0;
  52. do
  53. {
  54. if( m_result ) mysql_free_result( m_result );
  55. int errcode = mysql_query( pConnection, m_query.c_str() );
  56. m_result = mysql_store_result( pConnection );
  57. if( errcode == 0 )
  58. return true;
  59. m_status = mysql_errno( pConnection );
  60. m_reason = mysql_error( pConnection );
  61. mysql_ping( pConnection );
  62. retry++;
  63. } while( retry <= 1 );
  64. return success();
  65. }
  66. bool success()
  67. {
  68. return m_status == 0;
  69. }
  70. int rows()
  71. {
  72. return (int)mysql_num_rows( m_result );
  73. }
  74. const std::string& reason()
  75. {
  76. return m_reason;
  77. }
  78. char* getValue( int row, int column )
  79. {
  80. if( m_rows.empty() )
  81. {
  82. MYSQL_ROW row = 0;
  83. while( (row = mysql_fetch_row( m_result )) )
  84. m_rows.push_back(row);
  85. }
  86. return m_rows[row][column];
  87. }
  88. void throwException() throw( IOException )
  89. {
  90. if( !success() )
  91. throw IOException( "Query failed [" + m_query + "] " + reason() );
  92. }
  93. private:
  94. MYSQL_RES* m_result;
  95. int m_status;
  96. std::string m_query;
  97. std::string m_reason;
  98. std::vector<MYSQL_ROW> m_rows;
  99. };
  100. class MySQLConnection
  101. {
  102. public:
  103. MySQLConnection
  104. ( const DatabaseConnectionID& id )
  105. : m_connectionID( id )
  106. {
  107. connect();
  108. }
  109. MySQLConnection
  110. ( const std::string& database, const std::string& user,
  111. const std::string& password, const std::string& host, short port )
  112. : m_connectionID( database, user, password, host, port )
  113. {
  114. connect();
  115. }
  116. ~MySQLConnection()
  117. {
  118. if( m_pConnection )
  119. mysql_close( m_pConnection );
  120. }
  121. const DatabaseConnectionID& connectionID()
  122. {
  123. return m_connectionID;
  124. }
  125. bool connected()
  126. {
  127. Locker locker( m_mutex );
  128. return mysql_ping( m_pConnection ) == 0;
  129. }
  130. bool reconnect()
  131. {
  132. Locker locker( m_mutex );
  133. return mysql_ping( m_pConnection ) == 0;
  134. }
  135. bool execute( MySQLQuery& pQuery )
  136. {
  137. Locker locker( m_mutex );
  138. return pQuery.execute( m_pConnection );
  139. }
  140. private:
  141. void connect()
  142. {
  143. short port = m_connectionID.getPort();
  144. m_pConnection = mysql_init( NULL );
  145. if( !mysql_real_connect
  146. ( m_pConnection, m_connectionID.getHost().c_str(), m_connectionID.getUser().c_str(),
  147. m_connectionID.getPassword().c_str(), m_connectionID.getDatabase().c_str(), port, 0, 0 ) )
  148. {
  149. if( !connected() )
  150. throw ConfigError( std::string("Unable to connect to database [") + mysql_error(m_pConnection) + "]" );
  151. }
  152. #if( MYSQL_VERSION_ID > 50000 )
  153. my_bool reconnect = 1;
  154. mysql_options( m_pConnection, MYSQL_OPT_RECONNECT, static_cast<char*>(&reconnect) );
  155. #endif
  156. }
  157. MYSQL* m_pConnection;
  158. DatabaseConnectionID m_connectionID;
  159. Mutex m_mutex;
  160. };
  161. typedef DatabaseConnectionPool<MySQLConnection>
  162. MySQLConnectionPool;
  163. typedef std::auto_ptr< MySQLConnectionPool >
  164. MySQLConnectionPoolPtr;
  165. }
  166. #endif //FIX_MYSQLCONNECTION_H
  167. #endif //HAVE_MYSQL