00001 #include "../include/OdbcDatabaseLayer.h"
00002 #include "../include/OdbcPreparedStatement.h"
00003 #include "../include/OdbcResultSet.h"
00004 #include "../include/DatabaseErrorCodes.h"
00005
00006
00007
00008 OdbcDatabaseLayer::OdbcDatabaseLayer()
00009 : DatabaseLayer()
00010 {
00011 ResetErrorCodes();
00012
00013 SQLRETURN nRet = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_sqlEnvHandle);
00014 if ( nRet != SQL_SUCCESS )
00015 {
00016 InterpretErrorCodes( nRet );
00017 ThrowDatabaseException();
00018 }
00019
00020 nRet = SQLSetEnvAttr(m_sqlEnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
00021 if ( nRet != SQL_SUCCESS )
00022 {
00023 InterpretErrorCodes( nRet );
00024 ThrowDatabaseException();
00025 }
00026
00027 nRet = SQLAllocHandle(SQL_HANDLE_DBC, m_sqlEnvHandle, &m_sqlHDBC);
00028 if ( nRet != SQL_SUCCESS )
00029 {
00030 InterpretErrorCodes( nRet );
00031 ThrowDatabaseException();
00032 }
00033
00034 m_sqlStatementHandle = NULL;
00035
00036 m_strDSN = wxEmptyString;
00037 m_strUser = wxEmptyString;
00038 m_strPassword = wxEmptyString;
00039 m_strConnection = wxEmptyString;
00040 #if wxUSE_GUI
00041 m_bPrompt = false;
00042 m_pParent = NULL;
00043 #endif
00044 }
00045
00046 OdbcDatabaseLayer::~OdbcDatabaseLayer()
00047 {
00048 Close();
00049
00050 SQLRETURN nRet = SQLFreeHandle(SQL_HANDLE_DBC, m_sqlHDBC);
00051 if ( nRet != SQL_SUCCESS )
00052 {
00053 InterpretErrorCodes( nRet );
00054 ThrowDatabaseException();
00055 }
00056
00057 nRet = SQLFreeHandle(SQL_HANDLE_ENV, m_sqlEnvHandle);
00058 if ( nRet != SQL_SUCCESS )
00059 {
00060 InterpretErrorCodes( nRet );
00061 ThrowDatabaseException();
00062 }
00063 }
00064
00065 bool OdbcDatabaseLayer::Open( )
00066 {
00067 ResetErrorCodes();
00068
00069 if ( !m_strDSN.IsEmpty() )
00070 {
00071
00072
00073
00074 void* dsnCharBuffer = (void*)m_strDSN.c_str();
00075 void* userCharBuffer = (void*)m_strUser.c_str();
00076 void* passwordCharBuffer = (void*)m_strPassword.c_str();
00077
00078 SQLRETURN nRet;
00079 nRet = SQLConnect(m_sqlHDBC, (SQLTCHAR FAR*)(const char*)dsnCharBuffer,
00080 SQL_NTS, (SQLTCHAR FAR*)(const char*)userCharBuffer, SQL_NTS,
00081 (SQLTCHAR FAR*)(const char*)passwordCharBuffer, SQL_NTS);
00082 if ( nRet != SQL_SUCCESS )
00083 {
00084 InterpretErrorCodes( nRet );
00085 ThrowDatabaseException();
00086 }
00087 }
00088 else if ( !m_strConnection.IsEmpty() )
00089 {
00090 SQLTCHAR buff[8192];
00091 SQLSMALLINT iLen;
00092
00093 memset(buff, 0, 8192*sizeof(SQLTCHAR));
00094
00095
00096 void* connectionCharBuffer = (void*)m_strConnection.c_str();
00097 #if wxUSE_GUI
00098 SQLRETURN nRet = SQLDriverConnect(m_sqlHDBC, m_pParent ? (SQLHWND)m_pParent->GetHandle() : NULL, (SQLTCHAR*)(const char*)connectionCharBuffer,
00099 (SQLSMALLINT)m_strConnection.Length(), (SQLTCHAR*)buff, 8192, &iLen, m_bPrompt ? SQL_DRIVER_PROMPT : SQL_DRIVER_NOPROMPT);
00100 #else
00101 SQLRETURN nRet = SQLDriverConnect(m_sqlHDBC, NULL, (SQLTCHAR*)(const char*)connectionCharBuffer,
00102 (SQLSMALLINT)m_strConnection.Length(), (SQLTCHAR*)buff, 8192, &iLen, SQL_DRIVER_NOPROMPT);
00103 #endif
00104
00105 if ( nRet != SQL_SUCCESS )
00106 {
00107 InterpretErrorCodes( nRet );
00108 ThrowDatabaseException();
00109 }
00110 }
00111 else
00112 {
00113 return false;
00114 }
00115
00116 m_bIsConnected = true;
00117
00118 return true;
00119 }
00120
00121 bool OdbcDatabaseLayer::Open( const wxString& strConnection )
00122 {
00123 m_strDSN = wxEmptyString;
00124 m_strUser = wxEmptyString;
00125 m_strPassword = wxEmptyString;
00126 m_strConnection = strConnection;
00127 #if wxUSE_GUI
00128 m_bPrompt = false;
00129 m_pParent = NULL;
00130 #endif
00131
00132 return Open();
00133 }
00134
00135 #if wxUSE_GUI
00136 bool OdbcDatabaseLayer::Open(const wxString& strConnection, bool bPromptForInfo, wxWindow* parent)
00137 {
00138 m_strConnection = strConnection;
00139 m_bPrompt = bPromptForInfo;
00140 m_pParent = parent;
00141 m_strDSN = wxEmptyString;
00142 m_strUser = wxEmptyString;
00143 m_strPassword = wxEmptyString;
00144
00145 return Open();
00146 }
00147 #endif
00148
00149 bool OdbcDatabaseLayer::Open( const wxString& strDSN, const wxString& strUser, const wxString& strPassword )
00150 {
00151 m_strDSN = strDSN;
00152 m_strUser = strUser;
00153 m_strPassword = strPassword;
00154 m_strConnection = wxEmptyString;
00155 #if wxUSE_GUI
00156 m_bPrompt = false;
00157 m_pParent = NULL;
00158 #endif
00159
00160 return Open();
00161 }
00162
00163 bool OdbcDatabaseLayer::Close()
00164 {
00165 ResetErrorCodes();
00166
00167 CloseResultSets();
00168 CloseStatements();
00169
00170 if (m_bIsConnected)
00171 {
00172 SQLRETURN nRet = SQLDisconnect(m_sqlHDBC);
00173 if ( nRet != SQL_SUCCESS )
00174 {
00175 InterpretErrorCodes( nRet );
00176 ThrowDatabaseException();
00177 }
00178
00179 m_bIsConnected=false;
00180 }
00181
00182 return true;
00183 }
00184
00185 void OdbcDatabaseLayer::BeginTransaction()
00186 {
00187 ResetErrorCodes();
00188
00189 SQLRETURN nRet = SQLSetConnectAttr(m_sqlHDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
00190 if ( nRet != SQL_SUCCESS )
00191 {
00192 InterpretErrorCodes( nRet );
00193 ThrowDatabaseException();
00194 }
00195 }
00196
00197 void OdbcDatabaseLayer::Commit()
00198 {
00199 ResetErrorCodes();
00200
00201 SQLRETURN nRet = SQLEndTran(SQL_HANDLE_DBC, m_sqlHDBC, SQL_COMMIT);
00202 if ( nRet != SQL_SUCCESS )
00203 {
00204 InterpretErrorCodes( nRet );
00205 ThrowDatabaseException();
00206 }
00207
00208 nRet = SQLSetConnectAttr(m_sqlHDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
00209 if ( nRet != SQL_SUCCESS )
00210 {
00211 InterpretErrorCodes( nRet );
00212 ThrowDatabaseException();
00213 }
00214 }
00215
00216 void OdbcDatabaseLayer::RollBack()
00217 {
00218 ResetErrorCodes();
00219
00220 SQLRETURN nRet = SQLEndTran(SQL_HANDLE_DBC, m_sqlHDBC, SQL_ROLLBACK);
00221 if ( nRet != SQL_SUCCESS )
00222 {
00223 InterpretErrorCodes( nRet );
00224 ThrowDatabaseException();
00225 }
00226
00227 nRet = SQLSetConnectAttr(m_sqlHDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
00228 if ( nRet != SQL_SUCCESS )
00229 {
00230 InterpretErrorCodes( nRet );
00231 ThrowDatabaseException();
00232 }
00233 }
00234
00235 bool OdbcDatabaseLayer::RunQuery( const wxString& strQuery, bool bParseQuery )
00236 {
00237 ResetErrorCodes();
00238
00239
00240 OdbcPreparedStatement* pStatement = (OdbcPreparedStatement*)PrepareStatement( strQuery, bParseQuery );
00241
00242 if ( pStatement )
00243 {
00244 try
00245 {
00246 pStatement->RunQuery();
00247 wxDELETE( pStatement );
00248 return true;
00249 }
00250 catch (...)
00251 {
00252 wxDELETE( pStatement );
00253 ThrowDatabaseException();
00254 return false;
00255 }
00256 }
00257 else
00258 return false;
00259 }
00260
00261 DatabaseResultSet* OdbcDatabaseLayer::RunQueryWithResults(const wxString& strQuery)
00262 {
00263 ResetErrorCodes();
00264
00265 OdbcPreparedStatement* pStatement = (OdbcPreparedStatement*)PrepareStatement( strQuery, true );
00266
00267 if ( pStatement )
00268 {
00269 try
00270 {
00271 pStatement->SetOneTimer(true);
00272 DatabaseResultSet* pResults = pStatement->RunQueryWithResults(false );
00273 LogResultSetForCleanup(pResults);
00274 return pResults;
00275 }
00276 catch (...)
00277 {
00278 wxDELETE( pStatement );
00279 ThrowDatabaseException();
00280 return NULL;
00281 }
00282 }
00283 else
00284 return NULL;
00285 }
00286
00287 SQLHANDLE OdbcDatabaseLayer::allocStmth()
00288 {
00289 ResetErrorCodes();
00290
00291 SQLHANDLE handle = NULL;
00292
00293 SQLRETURN nRet = SQLAllocHandle (SQL_HANDLE_STMT, m_sqlHDBC, &handle);
00294 if ( nRet != SQL_SUCCESS )
00295 {
00296 InterpretErrorCodes( nRet );
00297 ThrowDatabaseException();
00298 }
00299 return handle;
00300 }
00301
00302 PreparedStatement* OdbcDatabaseLayer::PrepareStatement( const wxString& strQuery )
00303 {
00304 PreparedStatement* pStatement = PrepareStatement(strQuery, true);
00305 LogStatementForCleanup(pStatement);
00306 return pStatement;
00307 }
00308
00309 PreparedStatement* OdbcDatabaseLayer::PrepareStatement( const wxString& strQuery, bool bParseQuery )
00310 {
00311 ResetErrorCodes();
00312
00313 wxArrayString QueryArray;
00314 if (bParseQuery)
00315 QueryArray = ParseQueries(strQuery);
00316 else
00317 QueryArray.push_back(strQuery);
00318
00319 OdbcPreparedStatement* pReturnStatement = new OdbcPreparedStatement(m_sqlEnvHandle, m_sqlHDBC);
00320
00321 if (pReturnStatement)
00322 pReturnStatement->SetEncoding(GetEncoding());
00323
00324 for (unsigned int i=0; i<(QueryArray.size()); i++)
00325 {
00326
00327 void* sqlBuffer = (void*)(QueryArray[i].c_str());
00328
00329
00330 SQLHSTMT pSqlStatement = allocStmth();
00331 SQLRETURN nRet = SQLPrepare(pSqlStatement, (SQLTCHAR*)(const char*)sqlBuffer, SQL_NTS);
00332 if ( nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO )
00333 {
00334 InterpretErrorCodes( nRet );
00335 ThrowDatabaseException();
00336 return NULL;
00337 }
00338
00339 if ( pSqlStatement )
00340 pReturnStatement->AddPreparedStatement( pSqlStatement );
00341 }
00342
00343 return pReturnStatement;
00344 }
00345
00346 void OdbcDatabaseLayer::InterpretErrorCodes( long nCode, SQLHSTMT stmth_ptr )
00347 {
00348 wxLogDebug(_("OdbcDatabaseLayer::InterpretErrorCodes()\n"));
00349
00350
00351 {
00352 SQLINTEGER iNativeCode;
00353 SQLTCHAR strState[ERR_STATE_LEN];
00354 SQLTCHAR strBuffer[ERR_BUFFER_LEN];
00355 SQLSMALLINT iMsgLen;
00356
00357 memset(strState, 0, ERR_STATE_LEN*sizeof(SQLTCHAR));
00358 memset(strBuffer, 0, ERR_BUFFER_LEN*sizeof(SQLTCHAR));
00359
00360 if (stmth_ptr)
00361 SQLGetDiagRec(SQL_HANDLE_STMT, stmth_ptr, 1, strState, &iNativeCode,
00362 strBuffer, ERR_BUFFER_LEN, &iMsgLen);
00363 else
00364 SQLGetDiagRec(SQL_HANDLE_DBC, m_sqlHDBC, 1, strState, &iNativeCode,
00365 strBuffer, ERR_BUFFER_LEN, &iMsgLen);
00366
00367 SetErrorCode((int)iNativeCode);
00368
00369 SetErrorMessage(wxString((wxChar*)strBuffer));
00370 }
00371 }
00372