OdbcConnection.h
Go to the documentation of this file.
1/* -*- C++ -*- */
2
3/****************************************************************************
4** Copyright (c) 2001-2014
5**
6** This file is part of the QuickFIX FIX Engine
7**
8** This file may be distributed under the terms of the quickfixengine.org
9** license as defined by quickfixengine.org and appearing in the file
10** LICENSE included in the packaging of this file.
11**
12** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14**
15** See http://www.quickfixengine.org/LICENSE for licensing information.
16**
17** Contact ask@quickfixengine.org if any conditions of this licensing are
18** not clear to you.
19**
20****************************************************************************/
21
22#ifndef HAVE_ODBC
23#error OdbcConnection.h included, but HAVE_ODBC not defined
24#endif
25
26#ifdef HAVE_ODBC
27#ifndef FIX_ODBCCONNECTION_H
28#define FIX_ODBCCONNECTION_H
29
30#ifdef _MSC_VER
31#pragma warning( disable : 4503 4355 4786 4290 )
32#pragma comment( lib, "Odbc32" )
33#endif
34
35#include "Utility.h"
36#include <sql.h>
37#include <sqlext.h>
38#include <sqltypes.h>
39#include <sstream>
42#include "Exceptions.h"
43#include "Mutex.h"
44
45namespace FIX
46{
47
48inline std::string odbcError( SQLSMALLINT statementType, SQLHANDLE handle )
49{
50 SQLCHAR state[6];
51 SQLINTEGER error;
52 SQLCHAR text[SQL_MAX_MESSAGE_LENGTH];
53 SQLSMALLINT textLength;
54 RETCODE result = SQLGetDiagRec
55 ( statementType, handle, 1, state, &error, text, sizeof(text), &textLength );
56 if( result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO )
57 return std::string( (char*)text );
58 return "";
59}
60
61inline bool odbcSuccess( RETCODE result )
62{
63 return result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO;
64}
65
66class OdbcQuery
67{
68public:
69 OdbcQuery( const std::string& query )
70 : m_statement( 0 ), m_result( 0 ), m_query( query )
71 {}
72
73 ~OdbcQuery()
74 {
75 close();
76 }
77
78 void close()
79 {
80 if( m_statement )
81 {
82 SQLFreeHandle( SQL_HANDLE_STMT, m_statement );
83 m_statement = 0;
84 m_result = 0;
85 }
86 }
87
88 bool execute( HDBC connection )
89 {
90 if( m_statement ) SQLFreeHandle( SQL_HANDLE_STMT, m_statement );
91 SQLAllocHandle( SQL_HANDLE_STMT, connection, &m_statement );
92 m_result = SQLExecDirect( m_statement, (SQLCHAR*)m_query.c_str(), m_query.size() );
93 if( success() || m_result == SQL_NO_DATA )
94 return true;
95 m_reason = odbcError( SQL_HANDLE_STMT, m_statement );
96 SQLFreeHandle( SQL_HANDLE_STMT, m_statement );
97 m_statement = 0;
98 return success();
99 }
100
101 bool success()
102 {
103 return odbcSuccess( m_result );
104 }
105
106 /*int rows()
107 {
108 return (int)mysql_num_rows( m_result );
109 }*/
110
111 const std::string& reason()
112 {
113 return m_reason;
114 }
115
116 bool fetch()
117 {
118 return odbcSuccess( SQLFetch(m_statement) );
119 }
120
121 /*char* getValue( int row, int column )
122 {
123 if( m_rows.empty() )
124 {
125 MYSQL_ROW row = 0;
126 while( row = mysql_fetch_row( m_result ) )
127 m_rows.push_back(row);
128 }
129 return m_rows[row][column];
130 }*/
131
132 HSTMT statement()
133 {
134 return m_statement;
135 }
136
137 void throwException() throw( IOException )
138 {
139 if( !success() )
140 throw IOException( "Query failed [" + m_query + "] " + reason() );
141 }
142
143private:
144 HSTMT m_statement;
145 RETCODE m_result;
146 std::string m_query;
147 std::string m_reason;
148};
149
150class OdbcConnection
151{
152public:
153 OdbcConnection
154 ( const DatabaseConnectionID& id )
155 : m_connection( 0 ), m_environment( 0 ), m_connectionID( id )
156 {
157 connect();
158 }
159
160 OdbcConnection
161 ( const std::string& user, const std::string& password,
162 const std::string& connectionString )
163 : m_connection( 0 ), m_environment( 0 ), m_connectionID( "", user, password, connectionString, 0 )
164 {
165 connect();
166 }
167
168 ~OdbcConnection()
169 {
170 if( m_connection )
171 {
172 SQLDisconnect( m_connection );
173 SQLFreeHandle( SQL_HANDLE_DBC, m_connection );
174 SQLFreeHandle( SQL_HANDLE_ENV, m_environment );
175 }
176 }
177
178 const DatabaseConnectionID& connectionID()
179 {
180 return m_connectionID;
181 }
182
183 bool connected()
184 {
185 Locker locker( m_mutex );
186 return m_connected;
187 }
188
189 bool reconnect()
190 {
191 Locker locker( m_mutex );
192 SQLDisconnect( m_connection );
193 SQLFreeHandle( SQL_HANDLE_DBC, m_connection );
194 m_connection = 0;
195 connect();
196 return true;
197 }
198
199 bool execute( OdbcQuery& pQuery )
200 {
201 Locker locker( m_mutex );
202 if( !pQuery.execute( m_connection ) )
203 {
204 reconnect();
205 return pQuery.execute( m_connection );
206 }
207 return true;
208 }
209
210private:
211 void connect()
212 {
213 m_connected = false;
214
215 RETCODE result;
216 if(!m_environment)
217 {
218 result = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_environment );
219 if( !odbcSuccess(result) )
220 throw ConfigError( "Unable to allocate ODBC environment" );
221
222 result = SQLSetEnvAttr(m_environment, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
223 if( !odbcSuccess(result) )
224 throw ConfigError( "Unable to find ODBC version 3.0" );
225 }
226
227 result = SQLAllocHandle( SQL_HANDLE_DBC, m_environment, &m_connection );
228 if( !odbcSuccess(result) )
229 throw ConfigError( "Unable to allocate ODBC connection" );
230
231 std::stringstream connectionStream;
232 std::string connectionString = m_connectionID.getHost();
233 if( m_connectionID.getHost().find("UID=") == std::string::npos )
234 connectionStream << "UID=" << m_connectionID.getUser() << ";";
235 if( m_connectionID.getHost().find("PWD=") == std::string::npos )
236 connectionStream << "PWD=" << m_connectionID.getPassword() << ";";
237 connectionStream << m_connectionID.getHost();
238 connectionString = connectionStream.str();
239
240 SQLCHAR connectionStringOut[255];
241
242 result = SQLDriverConnect(
243 m_connection, NULL,
244 (SQLCHAR*)connectionString.c_str(), SQL_NTS,
245 connectionStringOut, 255,
246 0, SQL_DRIVER_NOPROMPT );
247
248 if( !odbcSuccess(result) )
249 {
250 std::string error = odbcError( SQL_HANDLE_DBC, m_connection );
251 throw ConfigError( error );
252 }
253
254 m_connected = true;
255 }
256
257 HENV m_environment;
258 HDBC m_connection;
259 bool m_connected;
260 DatabaseConnectionID m_connectionID;
261 Mutex m_mutex;
262};
263}
264
265#endif
266#endif

Generated on Mon Oct 14 2024 06:04:44 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001