Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

MysqlDatabaseLayer.cpp

Go to the documentation of this file.
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 // ctor
00009 MysqlDatabaseLayer::MysqlDatabaseLayer()
00010  : DatabaseLayer()
00011 {
00012   InitDatabase();
00013   m_strServer = _("localhost");
00014   m_iPort = 3306; // default
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; // default
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; // default
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 // dtor
00063 MysqlDatabaseLayer::~MysqlDatabaseLayer()
00064 {
00065   Close();
00066   //mysql_close(m_pDatabase);
00067   //delete m_pDatabase;
00068   //mysql_library_end();
00069   mysql_server_end();
00070 }
00071 
00072 // open database
00073 void MysqlDatabaseLayer::InitDatabase()
00074 {
00075   //char *server_options[] = { "mysql_test", "--defaults-file=my.cnf" };
00076   //int num_elements = sizeof(server_options)/ sizeof(char *);
00077 
00078   //char *server_groups[] = { "libmysqld_server", "libmysqld_client" };
00079   //mysql_server_init(num_elements, server_options, server_groups);
00080   //m_pDatabase = new MYSQL();
00081   //mysql_library_init();
00082   //mysql_init(m_pDatabase);
00083   mysql_server_init( 0, NULL, NULL );
00084   m_pDatabase = mysql_init(NULL);
00085 }
00086 
00087 // open database
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/*socket*/, 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; // default
00152   }
00153 }
00154 
00155 // close database
00156 bool MysqlDatabaseLayer::Close()
00157 {
00158   CloseResultSets();
00159   CloseStatements();
00160 
00161   ResetErrorCodes();
00162 /*
00163 #if wxUSE_UNICODE
00164   // Iterate through all the result sets and close any open ones
00165   PointerLookupMap::iterator ResultSetStart = m_ResultSets.begin();
00166   PointerLookupMap::iterator ResultSetStop = m_ResultSets.end();
00167 
00168   while (ResultSetStart != ResultSetStop)
00169   {
00170     delete (MysqlPreparedStatementResultSet*)((*ResultSetStart).first);
00171     if ((*ResultSetStart).second != NULL)
00172     {
00173         MYSQL_STMT* pStatement = (MYSQL_STMT*)((*ResultSetStart).second);
00174         wxPrintf(_("Closing statement %d\n"), pStatement);
00175         mysql_stmt_close(pStatement);
00176     }
00177     ResultSetStart++;  
00178   }
00179   m_ResultSets.clear();
00180 #endif
00181 */
00182   mysql_close(m_pDatabase);
00183   mysql_server_end();
00184   //delete m_pDatabase;
00185   //m_pDatabase = NULL;
00186   return true;
00187 }
00188 
00189   
00190 // transaction support
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 // query database
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     //puts(sqlBuffer);
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       //puts(sqlBuffer);
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         //wxPrintf(_("Allocating statement at %d\n"), pMysqlStatement);
00317        // m_ResultSets[pResultSet] = pMysqlStatement;
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 void MysqlDatabaseLayer::CloseResultSet(DatabaseResultSet* pResultSet)
00339 {
00340   if (pResultSet != NULL)
00341   {
00342     //pResultSet->Close();
00343     delete pResultSet;
00344 
00345     // If the result set is registered in the map, then delete any associated mysql statements
00346     //  and remove from the map
00347 #if wxUSE_UNICODE
00348     PointerLookupMap::iterator finder = m_ResultSets.find(pResultSet);
00349     if (finder != m_ResultSets.end())
00350     {
00351       if ((*finder).second != NULL)
00352       {
00353         MYSQL_STMT* pStatement = (MYSQL_STMT*)((*finder).second);
00354         //wxPrintf(_("deleting statement at %d\n"), m_ResultSets[pResultSet]);
00355         mysql_stmt_close((MYSQL_STMT*)(m_ResultSets[pResultSet]));
00356       }
00357       m_ResultSets.erase(pResultSet);
00358     }
00359 #endif
00360   }
00361 }
00362 */
00363 
00364 // PreparedStatement support
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       //puts(sqlBuffer);
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   // Ultimately, this will probably be a map of Mysql database error code values to DatabaseLayer values
00411   // For now though, we'll just return error
00412   return nCode;
00413   //return DATABASE_LAYER_ERROR;
00414 }
00415 

Generated on Sat May 13 17:31:34 2006 for databaselayer by  doxygen 1.4.1