00001 #include "../include/MysqlDatabaseLayer.h"
00002 #include "../include/MysqlPreparedStatement.h"
00003 #include "../include/MysqlPreparedStatementResultSet.h"
00004 #include "../include/DatabaseErrorCodes.h"
00005
00006 #include <wx/tokenzr.h>
00007
00008
00009 MysqlDatabaseLayer::MysqlDatabaseLayer()
00010 : DatabaseLayer()
00011 {
00012 InitDatabase();
00013 m_strServer = _("localhost");
00014 m_iPort = 3306;
00015 m_strDatabase = _("");
00016 m_strUser = _("");
00017 m_strPassword = _("");
00018 }
00019
00020 MysqlDatabaseLayer::MysqlDatabaseLayer(const wxString& strDatabase)
00021 : DatabaseLayer()
00022 {
00023 InitDatabase();
00024 m_strServer = _("localhost");
00025 m_iPort = 3306;
00026 m_strUser = _("");
00027 m_strPassword = _("");
00028 Open(strDatabase);
00029 }
00030
00031 MysqlDatabaseLayer::MysqlDatabaseLayer(const wxString& strServer, const wxString& strDatabase)
00032 : DatabaseLayer()
00033 {
00034 InitDatabase();
00035 ParseServerAndPort(strServer);
00036 m_strUser = _("");
00037 m_strPassword = _("");
00038 Open(strDatabase);
00039 }
00040
00041 MysqlDatabaseLayer::MysqlDatabaseLayer(const wxString& strDatabase, const wxString& strUser, const wxString& strPassword)
00042 : DatabaseLayer()
00043 {
00044 InitDatabase();
00045 m_strServer = _("localhost");
00046 m_iPort = 3306;
00047 m_strUser = strUser;
00048 m_strPassword = strPassword;
00049 Open(strDatabase);
00050 }
00051
00052 MysqlDatabaseLayer::MysqlDatabaseLayer(const wxString& strServer, const wxString& strDatabase, const wxString& strUser, const wxString& strPassword)
00053 : DatabaseLayer()
00054 {
00055 InitDatabase();
00056 ParseServerAndPort(strServer);
00057 m_strUser = strUser;
00058 m_strPassword = strPassword;
00059 Open(strDatabase);
00060 }
00061
00062
00063 MysqlDatabaseLayer::~MysqlDatabaseLayer()
00064 {
00065 Close();
00066
00067
00068
00069 mysql_server_end();
00070 }
00071
00072
00073 void MysqlDatabaseLayer::InitDatabase()
00074 {
00075
00076
00077
00078
00079
00080
00081
00082
00083 mysql_server_init( 0, NULL, NULL );
00084 m_pDatabase = mysql_init(NULL);
00085 }
00086
00087
00088 bool MysqlDatabaseLayer::Open(const wxString& strServer, const wxString& strDatabase)
00089 {
00090 ParseServerAndPort(strServer);
00091 return Open(strDatabase);
00092 }
00093
00094 bool MysqlDatabaseLayer::Open(const wxString& strDatabase, const wxString& strUser, const wxString& strPassword)
00095 {
00096 m_strUser = strUser;
00097 m_strPassword = strPassword;
00098 return Open(strDatabase);
00099 }
00100
00101 bool MysqlDatabaseLayer::Open(const wxString& strServer, const wxString& strDatabase, const wxString& strUser, const wxString& strPassword)
00102 {
00103 ParseServerAndPort(strServer);
00104 m_strUser = strUser;
00105 m_strPassword = strPassword;
00106 return Open(strDatabase);
00107 }
00108
00109 bool MysqlDatabaseLayer::Open(const wxString& strDatabase)
00110 {
00111 m_strDatabase = strDatabase;
00112
00113 wxCharBuffer serverCharBuffer = ConvertToUnicodeStream(m_strServer);
00114 wxCharBuffer userCharBuffer = ConvertToUnicodeStream(m_strUser);
00115 wxCharBuffer passwordCharBuffer = ConvertToUnicodeStream(m_strPassword);
00116 wxCharBuffer databaseNameCharBuffer = ConvertToUnicodeStream(m_strDatabase);
00117 if (mysql_real_connect(m_pDatabase, serverCharBuffer, userCharBuffer, passwordCharBuffer, databaseNameCharBuffer, m_iPort, NULL, 0) != NULL)
00118 {
00119 #if wxUSE_UNICODE
00120 const char* sqlStatement = "SET CHARACTER_SET_CLIENT=utf8, "
00121 "CHARACTER_SET_CONNECTION=utf8, "
00122 "CHARACTER_SET_RESULTS=utf8;";
00123
00124 mysql_real_query(m_pDatabase, sqlStatement, strlen(sqlStatement));
00125 wxCSConv conv(_("UTF-8"));
00126 SetEncoding(&conv);
00127 #endif
00128
00129 return true;
00130 }
00131 else
00132 {
00133 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00134 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00135 ThrowDatabaseException();
00136 return false;
00137 }
00138 }
00139
00140 void MysqlDatabaseLayer::ParseServerAndPort(const wxString& strServer)
00141 {
00142 int portIndicator = strServer.Find(_(":"));
00143 if (portIndicator > -1)
00144 {
00145 m_strServer = strServer.SubString(0, portIndicator-1);
00146 m_iPort = wxAtoi(strServer.SubString(portIndicator+1, strServer.Length()-1));
00147 }
00148 else
00149 {
00150 m_strServer = strServer;
00151 m_iPort = 3306;
00152 }
00153 }
00154
00155
00156 bool MysqlDatabaseLayer::Close()
00157 {
00158 CloseResultSets();
00159 CloseStatements();
00160
00161 ResetErrorCodes();
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 mysql_close(m_pDatabase);
00183 mysql_server_end();
00184
00185
00186 return true;
00187 }
00188
00189
00190
00191 void MysqlDatabaseLayer::BeginTransaction()
00192 {
00193 ResetErrorCodes();
00194
00195 int nReturn = mysql_autocommit(m_pDatabase, 0);
00196 if (nReturn != 0)
00197 {
00198 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00199 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00200 ThrowDatabaseException();
00201 }
00202 }
00203
00204 void MysqlDatabaseLayer::Commit()
00205 {
00206 ResetErrorCodes();
00207
00208 int nReturn = mysql_commit(m_pDatabase);
00209 if (nReturn != 0)
00210 {
00211 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00212 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00213 ThrowDatabaseException();
00214 }
00215 nReturn = mysql_autocommit(m_pDatabase, 1);
00216 if (nReturn != 0)
00217 {
00218 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00219 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00220 ThrowDatabaseException();
00221 }
00222 }
00223
00224 void MysqlDatabaseLayer::RollBack()
00225 {
00226 ResetErrorCodes();
00227
00228 int nReturn = mysql_rollback(m_pDatabase);
00229 if (nReturn != 0)
00230 {
00231 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00232 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00233 ThrowDatabaseException();
00234 }
00235 nReturn = mysql_autocommit(m_pDatabase, 1);
00236 if (nReturn != 0)
00237 {
00238 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00239 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00240 ThrowDatabaseException();
00241 }
00242 }
00243
00244
00245
00246 bool MysqlDatabaseLayer::RunQuery(const wxString& strQuery, bool bParseQuery)
00247 {
00248 ResetErrorCodes();
00249
00250 wxArrayString QueryArray;
00251 if (bParseQuery)
00252 QueryArray = ParseQueries(strQuery);
00253 else
00254 QueryArray.push_back(strQuery);
00255
00256 wxArrayString::iterator start = QueryArray.begin();
00257 wxArrayString::iterator stop = QueryArray.end();
00258
00259 while (start != stop)
00260 {
00261 wxCharBuffer sqlBuffer = ConvertToUnicodeStream(*start);
00262
00263 int nReturn = mysql_query(m_pDatabase, sqlBuffer);
00264 if (nReturn != 0)
00265 {
00266 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00267 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00268 ThrowDatabaseException();
00269 return false;
00270 }
00271 start++;
00272 }
00273 return true;
00274 }
00275
00276 DatabaseResultSet* MysqlDatabaseLayer::RunQueryWithResults(const wxString& strQuery)
00277 {
00278 ResetErrorCodes();
00279
00280 wxArrayString QueryArray = ParseQueries(strQuery);
00281
00282 int nArraySize = QueryArray.size();
00283 MysqlPreparedStatementResultSet* pResultSet = NULL;
00284 for (int i=0; i<nArraySize; i++)
00285 {
00286 wxString strCurrentQuery = QueryArray[i];
00287 MYSQL_STMT* pMysqlStatement = mysql_stmt_init(m_pDatabase);
00288 if (pMysqlStatement != NULL)
00289 {
00290 wxCharBuffer sqlBuffer = ConvertToUnicodeStream(strCurrentQuery);
00291
00292 wxString sqlUTF8((const char*)sqlBuffer, wxConvUTF8);
00293 if (mysql_stmt_prepare(pMysqlStatement, sqlBuffer, sqlUTF8.Length()) == 0)
00294 {
00295 int nReturn = mysql_stmt_execute(pMysqlStatement);
00296 if (nReturn != 0)
00297 {
00298 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_stmt_errno(pMysqlStatement)));
00299 SetErrorMessage(ConvertFromUnicodeStream(mysql_stmt_error(pMysqlStatement)));
00300 ThrowDatabaseException();
00301 return NULL;
00302 }
00303 }
00304 else
00305 {
00306 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00307 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00308 ThrowDatabaseException();
00309 }
00310 if (i == nArraySize-1)
00311 {
00312 pResultSet = new MysqlPreparedStatementResultSet(pMysqlStatement);
00313 if (pResultSet)
00314 pResultSet->SetEncoding(GetEncoding());
00315 #if wxUSE_UNICODE
00316
00317
00318 #endif
00319 LogResultSetForCleanup(pResultSet);
00320 return pResultSet;
00321 }
00322
00323 mysql_stmt_free_result(pMysqlStatement);
00324 mysql_stmt_close(pMysqlStatement);
00325 }
00326 else
00327 {
00328 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00329 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00330 ThrowDatabaseException();
00331 return NULL;
00332 }
00333 }
00334 LogResultSetForCleanup(pResultSet);
00335 return pResultSet;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 PreparedStatement* MysqlDatabaseLayer::PrepareStatement(const wxString& strQuery)
00366 {
00367 ResetErrorCodes();
00368
00369 wxArrayString QueryArray = ParseQueries(strQuery);
00370
00371 wxArrayString::iterator start = QueryArray.begin();
00372 wxArrayString::iterator stop = QueryArray.end();
00373
00374 MysqlPreparedStatement* pStatement = new MysqlPreparedStatement();
00375 if (pStatement)
00376 pStatement->SetEncoding(GetEncoding());
00377 while (start != stop)
00378 {
00379 MYSQL_STMT* pMysqlStatement = mysql_stmt_init(m_pDatabase);
00380 if (pMysqlStatement != NULL)
00381 {
00382 wxCharBuffer sqlBuffer = ConvertToUnicodeStream((*start));
00383
00384 if (mysql_stmt_prepare(pMysqlStatement, sqlBuffer, GetEncodedStreamLength((*start))) == 0)
00385 {
00386 pStatement->AddPreparedStatement(pMysqlStatement);
00387 }
00388 else
00389 {
00390 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00391 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00392 ThrowDatabaseException();
00393 }
00394 }
00395 else
00396 {
00397 SetErrorCode(MysqlDatabaseLayer::TranslateErrorCode(mysql_errno(m_pDatabase)));
00398 SetErrorMessage(ConvertFromUnicodeStream(mysql_error(m_pDatabase)));
00399 ThrowDatabaseException();
00400 return NULL;
00401 }
00402 start++;
00403 }
00404 LogStatementForCleanup(pStatement);
00405 return pStatement;
00406 }
00407
00408 int MysqlDatabaseLayer::TranslateErrorCode(int nCode)
00409 {
00410
00411
00412 return nCode;
00413
00414 }
00415