Logo
~Database~
~ C++ ~
~Contact~

Database.cpp

Go to the documentation of this file.
00001 /*
00002  **     Database.cpp
00003  **
00004  **     Published / author: 2006-03-29 / grymse@alhem.net
00005  **/
00006 /*
00007 Copyright (C) 2006 Anders Hedstrom
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022 */
00023 #ifdef _WIN32
00024 #pragma warning(disable:4786)
00025 #endif
00026 
00027 #ifdef _WIN32
00028 #include <afxdb.h>
00029 #include <sql.h>
00030 #endif
00031 
00032 #include "Database.h"
00033 #include "Query.h"
00034 #include "IError.h"
00035 #include "Session.h"
00036 
00037 
00038 #ifdef ODBCW_NAMESPACE
00039 namespace ODBCW_NAMESPACE {
00040 #endif
00041 
00042 
00043 Database::Database(const std::string& dsn,const std::string& u,const std::string& auth,IError *p)
00044 :m_driverconnect(0)
00045 ,m_host(dsn)
00046 ,m_user(u)
00047 ,m_password(auth)
00048 ,m_errc(0)
00049 ,m_escape('\'')
00050 ,m_decimal(',')
00051 ,m_errhandler(p)
00052 ,m_mutex(m_mutex)
00053 ,m_b_use_mutex(false)
00054 {
00055 }
00056 
00057 
00058 Database::Database(const std::string& driverconnect,IError *p)
00059 :m_driverconnect(1)
00060 ,m_host(driverconnect)
00061 ,m_errc(0)
00062 ,m_escape('\'')
00063 ,m_decimal(',')
00064 ,m_errhandler(p)
00065 ,m_mutex(m_mutex)
00066 ,m_b_use_mutex(false)
00067 {
00068 }
00069 
00070 
00071 Database::Database(Mutex& mutex,const std::string& dsn,const std::string& u,const std::string& auth,IError *p)
00072 :m_driverconnect(0)
00073 ,m_host(dsn)
00074 ,m_user(u)
00075 ,m_password(auth)
00076 ,m_errc(0)
00077 ,m_escape('\'')
00078 ,m_decimal(',')
00079 ,m_errhandler(p)
00080 ,m_mutex(mutex)
00081 ,m_b_use_mutex(true)
00082 {
00083 }
00084 
00085 
00086 Database::Database(Mutex& mutex,const std::string& driverconnect,IError *p)
00087 :m_driverconnect(1)
00088 ,m_host(driverconnect)
00089 ,m_errc(0)
00090 ,m_escape('\'')
00091 ,m_decimal(',')
00092 ,m_errhandler(p)
00093 ,m_mutex(mutex)
00094 ,m_b_use_mutex(true)
00095 {
00096 }
00097 
00098 
00099 Database::~Database()
00100 {
00101         for (std::list<Session *>::iterator it = m_sessions.begin(); it != m_sessions.end(); it++)
00102         {
00103                 if ((*it) -> IsBusy())
00104                 {
00105                         error("destroying Session object before Query object(s)\n");
00106                 }
00107                 Session *pSession = static_cast<Session*>(*it);
00108                 delete pSession;
00109         }
00110 }
00111 
00112 
00113 Session *Database::grabdb()
00114 {
00115         Lock lck(m_mutex, m_b_use_mutex);
00116         for (std::list<Session *>::iterator it = m_sessions.begin(); it != m_sessions.end(); it++)
00117         {
00118                 if (!(*it) -> IsBusy())
00119                 {
00120                         (*it) -> SetBusy(true);
00121                         return *it;
00122                 }
00123         }
00124         Session *tmp = new Session;
00125         int nResult;
00126         if (m_driverconnect)
00127         {
00128                 nResult = tmp -> Connect(*this, m_host);
00129         }
00130         else
00131         {
00132                 nResult = tmp -> Connect(*this, m_host,m_user,m_password);
00133         }
00134         if (nResult != 0)
00135         {
00136                 std::string strSqlState;
00137                 std::string strErrorMessage;
00138                 tmp -> GetLastError(strSqlState, strErrorMessage);
00139                 delete tmp;
00140                 throw strErrorMessage;
00141         }
00142         m_sessions.insert(m_sessions.end(), tmp);
00143         tmp -> SetBusy(true);
00144         return tmp;
00145 }
00146 
00147 void Database::freedb(Session *odb)
00148 {
00149         Lock lck(m_mutex, m_b_use_mutex);
00150         odb -> SetBusy(false);
00151 }
00152 
00153 
00154 short Database::errcode()
00155 {
00156         return m_errc;
00157 }
00158 
00159 
00160 void Database::GetErrorText(char *dest)
00161 {
00162         short rc = m_errc;
00163 
00164         switch (rc)
00165         {
00166         case -1:
00167                 sprintf(dest, "%d: SQLAllocHandle(SQL_HANDLE_ENV) failed", rc);
00168                 break;
00169         case -2:
00170                 sprintf(dest, "%d: SQLSetEnvAttr() failed", rc);
00171                 break;
00172         case -3:
00173                 sprintf(dest, "%d: SQLAllocHandle(SQL_HANDLE_DBC) failed", rc);
00174                 break;
00175         case -4:
00176                 sprintf(dest, "%d: SQLConnect(%s) failed", rc, m_host.c_str());
00177                 break;
00178 
00179         default:
00180                 sprintf(dest, "%d: Undefined error code", rc);
00181         }
00182 }
00183 
00184 
00185 Query *Database::GetQuery()
00186 {
00187         return new Query(*this);
00188 }
00189 
00190 
00191 Query *Database::GetQuery(const std::string& sql)
00192 {
00193         return new Query(*this, sql);
00194 }
00195 
00196 
00197 void Database::SetEscapeChar(char ch)
00198 {
00199         m_escape = ch;
00200 }
00201 
00202 
00203 char Database::GetEscapeChar()
00204 {
00205         return m_escape;
00206 }
00207 
00208 
00209 void Database::SetDecimalChar(char ch)
00210 {
00211         m_decimal = ch;
00212 }
00213 
00214 
00215 char Database::GetDecimalChar()
00216 {
00217         return m_decimal;
00218 }
00219 
00220 
00221 void Database::error(const std::string& text)
00222 {
00223         if (m_errhandler)
00224         {
00225                 m_errhandler -> error(*this, text);
00226         }
00227 }
00228 
00229 
00230 Database::Lock::Lock(Mutex& mutex,bool use) : m_mutex(mutex),m_b_use(use)
00231 {
00232         if (m_b_use)
00233         {
00234                 m_mutex.Lock();
00235         }
00236 }
00237 
00238 
00239 Database::Lock::~Lock()
00240 {
00241         if (m_b_use)
00242         {
00243                 m_mutex.Unlock();
00244         }
00245 }
00246 
00247 
00248 Database::Mutex::Mutex()
00249 {
00250 #ifdef _WIN32
00251         m_mutex = ::CreateMutex(NULL, FALSE, NULL);
00252 #else
00253         pthread_mutex_init(&m_mutex, NULL);
00254 #endif
00255 }
00256 
00257 
00258 Database::Mutex::~Mutex()
00259 {
00260 #ifdef _WIN32
00261         ::CloseHandle(m_mutex);
00262 #else
00263         pthread_mutex_destroy(&m_mutex);
00264 #endif
00265 }
00266 
00267 
00268 void Database::Mutex::Lock()
00269 {
00270 #ifdef _WIN32
00271         DWORD d = WaitForSingleObject(m_mutex, INFINITE);
00272         // %! check 'd' for result
00273 #else
00274         pthread_mutex_lock(&m_mutex);
00275 #endif
00276 }
00277 
00278 
00279 void Database::Mutex::Unlock()
00280 {
00281 #ifdef _WIN32
00282         ::ReleaseMutex(m_mutex);
00283 #else
00284         pthread_mutex_unlock(&m_mutex);
00285 #endif
00286 }
00287 
00288 
00289 std::string Database::safestr(const std::string& s)
00290 {
00291         std::string s2;
00292         for (size_t i = 0; i < s.size(); i++)
00293         {
00294                 switch (s[i])
00295                 {
00296                 case '\'':
00297                 case '\\':
00298                 case 34:
00299                         s2 += GetEscapeChar();
00300                 default:
00301                         s2 += s[i];
00302                 }
00303         }
00304         return s2;
00305 }
00306 
00307 
00308 std::string Database::xmlsafestr(const std::string& str)
00309 {
00310         std::string str2;
00311 
00312         for (size_t i = 0; i < str.size(); i++)
00313         {
00314                 switch (str[i])
00315                 {
00316                 case '&':
00317                         str2 += "&amp;";
00318                         break;
00319                 case '<':
00320                         str2 += "&lt;";
00321                         break;
00322                 case '>':
00323                         str2 += "&gt;";
00324                         break;
00325                 case '"':
00326                         str2 += "&quot;";
00327                         break;
00328                 case '\'':
00329                         str2 += "&apos;";
00330                         break;
00331                 default:
00332                         str2 += str[i];
00333                 }
00334         }
00335         return str2;
00336 }
00337 
00338 
00339 #ifdef ODBCW_NAMESPACE
00340 } // namespace ODBCW_NAMESPACE {
00341 #endif
Page, code, and content Copyright (C) 2006 by Anders Hedström