![]() |
Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members
Database.cppGo 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 += "&"; 00318 break; 00319 case '<': 00320 str2 += "<"; 00321 break; 00322 case '>': 00323 str2 += ">"; 00324 break; 00325 case '"': 00326 str2 += """; 00327 break; 00328 case '\'': 00329 str2 += "'"; 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 |