Index Source Files Annotated Class List Alphabetical Class List Class Hierarchy Graphical Class Hierarchy

# MySQLConnection.h

Go to the documentation of this file.

    00001 /* -*- C++ -*- */
    00002
    00003 /****************************************************************************
    00004 ** Copyright (c) quickfixengine.org  All rights reserved.
    00005 **
    00006 ** This file is part of the QuickFIX FIX Engine
    00007 **
    00008 ** This file may be distributed under the terms of the quickfixengine.org
    00009 ** license as defined by quickfixengine.org and appearing in the file
    00010 ** LICENSE included in the packaging of this file.
    00011 **
    00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    00014 **
    00015 ** See http://www.quickfixengine.org/LICENSE for licensing information.
    00016 **
    00017 ** Contact ask@quickfixengine.org if any conditions of this licensing are
    00018 ** not clear to you.
    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