Forums  +  C++ and Sockets  +  C++ and SQL: MySQL, sqlite, ODBC  +  Miscellaneous Projects
Logo
~Database~
~ C++ ~
~Contact~

Database.cpp

Go to the documentation of this file.
00001 /*
00002  **     Database.cpp
00003  **
00004  **     Published / author: 2005-08-12 / grymse@alhem.net
00005  **/
00006 
00007 /*
00008 Copyright (C) 2001-2006  Anders Hedstrom
00009 
00010 This program is made available under the terms of the GNU GPL.
00011 
00012 If you would like to use this program in a closed-source application,
00013 a separate license agreement is available. For information about 
00014 the closed-source license agreement for this program, please
00015 visit http://www.alhem.net/sqlwrapped/license.html and/or
00016 email license@alhem.net.
00017 
00018 This program is free software; you can redistribute it and/or
00019 modify it under the terms of the GNU General Public License
00020 as published by the Free Software Foundation; either version 2
00021 of the License, or (at your option) any later version.
00022 
00023 This program is distributed in the hope that it will be useful,
00024 but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 GNU General Public License for more details.
00027 
00028 You should have received a copy of the GNU General Public License
00029 along with this program; if not, write to the Free Software
00030 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00031 */
00032 #include <stdio.h>
00033 #ifdef _WIN32
00034 #pragma warning(disable:4786)
00035 #endif
00036 
00037 #include <string>
00038 #include <map>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <sqlite3.h>
00043 #include <stdarg.h>
00044 
00045 #include "IError.h"
00046 #include "Database.h"
00047 
00048 
00049 #ifdef SQLITEW_NAMESPACE
00050 namespace SQLITEW_NAMESPACE {
00051 #endif
00052 
00053 
00054 Database::Database(const std::string& d,IError *e)
00055 :database(d)
00056 ,m_errhandler(e)
00057 ,m_embedded(true)
00058 ,m_mutex(m_mutex)
00059 ,m_b_use_mutex(false)
00060 {
00061 }
00062 
00063 
00064 Database::Database(Mutex& m,const std::string& d,IError *e)
00065 :database(d)
00066 ,m_errhandler(e)
00067 ,m_embedded(true)
00068 ,m_mutex(m)
00069 ,m_b_use_mutex(true)
00070 {
00071 }
00072 
00073 
00074 Database::~Database()
00075 {
00076         for (opendb_v::iterator it = m_opendbs.begin(); it != m_opendbs.end(); it++)
00077         {
00078                 OPENDB *p = *it;
00079                 sqlite3_close(p -> db);
00080         }
00081         while (m_opendbs.size())
00082         {
00083                 opendb_v::iterator it = m_opendbs.begin();
00084                 OPENDB *p = *it;
00085                 if (p -> busy)
00086                 {
00087                         error("destroying Database object before Query object");
00088                 }
00089                 delete p;
00090                 m_opendbs.erase(it);
00091         }
00092 }
00093 
00094 
00095 void Database::RegErrHandler(IError *p)
00096 {
00097         m_errhandler = p;
00098 }
00099 
00100 
00101 Database::OPENDB *Database::grabdb()
00102 {
00103         Lock lck(m_mutex, m_b_use_mutex);
00104         OPENDB *odb = NULL;
00105 
00106         for (opendb_v::iterator it = m_opendbs.begin(); it != m_opendbs.end(); it++)
00107         {
00108                 odb = *it;
00109                 if (!odb -> busy)
00110                 {
00111                         break;
00112                 }
00113                 else
00114                 {
00115                         odb = NULL;
00116                 }
00117         }
00118         if (!odb)
00119         {
00120                 odb = new OPENDB;
00121                 if (!odb)
00122                 {
00123                         error("grabdb: OPENDB struct couldn't be created");
00124                         return NULL;
00125                 }
00126                 int rc = sqlite3_open(database.c_str(), &odb -> db);
00127                 if (rc)
00128                 {
00129                         error("Can't open database: %s\n", sqlite3_errmsg(odb -> db));
00130                         sqlite3_close(odb -> db);
00131                         delete odb;
00132                         return NULL;
00133                 }
00134                 odb -> busy = true;
00135                 m_opendbs.push_back(odb);
00136         }
00137         else
00138         {
00139                 odb -> busy = true;
00140         }
00141         return odb;
00142 }
00143 
00144 
00145 void Database::freedb(Database::OPENDB *odb)
00146 {
00147         Lock lck(m_mutex, m_b_use_mutex);
00148         if (odb)
00149         {
00150                 odb -> busy = false;
00151         }
00152 }
00153 
00154 
00155 void Database::error(const char *format, ...)
00156 {
00157         if (m_errhandler)
00158         {
00159                 va_list ap;
00160                 char errstr[5000];
00161                 va_start(ap, format);
00162 #ifdef WIN32
00163                 vsprintf(errstr, format, ap);
00164 #else
00165                 vsnprintf(errstr, 5000, format, ap);
00166 #endif
00167                 va_end(ap);
00168                 m_errhandler -> error(*this, errstr);
00169         }
00170 }
00171 
00172 
00173 void Database::error(Query& q,const char *format, ...)
00174 {
00175         if (m_errhandler)
00176         {
00177                 va_list ap;
00178                 char errstr[5000];
00179                 va_start(ap, format);
00180 #ifdef WIN32
00181                 vsprintf(errstr, format, ap);
00182 #else
00183                 vsnprintf(errstr, 5000, format, ap);
00184 #endif
00185                 va_end(ap);
00186                 m_errhandler -> error(*this, q, errstr);
00187         }
00188 }
00189 
00190 
00191 void Database::error(Query& q,const std::string& msg)
00192 {
00193         if (m_errhandler)
00194         {
00195                 m_errhandler -> error(*this, q, msg);
00196         }
00197 }
00198 
00199 
00200 bool Database::Connected()
00201 {
00202         OPENDB *odb = grabdb();
00203         if (!odb)
00204         {
00205                 return false;
00206         }
00207         freedb(odb);
00208         return true;
00209 }
00210 
00211 
00212 Database::Lock::Lock(Mutex& mutex,bool use) : m_mutex(mutex),m_b_use(use) 
00213 {
00214         if (m_b_use) 
00215         {
00216                 m_mutex.Lock();
00217         }
00218 }
00219 
00220 
00221 Database::Lock::~Lock() 
00222 {
00223         if (m_b_use) 
00224         {
00225                 m_mutex.Unlock();
00226         }
00227 }
00228 
00229 
00230 Database::Mutex::Mutex()
00231 {
00232 #ifdef _WIN32
00233         m_mutex = ::CreateMutex(NULL, FALSE, NULL);
00234 #else
00235         pthread_mutex_init(&m_mutex, NULL);
00236 #endif
00237 }
00238 
00239 
00240 Database::Mutex::~Mutex()
00241 {
00242 #ifdef _WIN32
00243         ::CloseHandle(m_mutex);
00244 #else
00245         pthread_mutex_destroy(&m_mutex);
00246 #endif
00247 }
00248 
00249 
00250 void Database::Mutex::Lock()
00251 {
00252 #ifdef _WIN32
00253         DWORD d = WaitForSingleObject(m_mutex, INFINITE);
00254         // %! check 'd' for result
00255 #else
00256         pthread_mutex_lock(&m_mutex);
00257 #endif
00258 }
00259 
00260 
00261 void Database::Mutex::Unlock()
00262 {
00263 #ifdef _WIN32
00264         ::ReleaseMutex(m_mutex);
00265 #else
00266         pthread_mutex_unlock(&m_mutex);
00267 #endif
00268 }
00269 
00270 
00271 std::string Database::safestr(const std::string& str)
00272 {
00273         std::string str2;
00274         for (size_t i = 0; i < str.size(); i++)
00275         {
00276                 switch (str[i])
00277                 {
00278                 case '\'':
00279                 case '\\':
00280                 case 34:
00281                         str2 += '\'';
00282                 default:
00283                         str2 += str[i];
00284                 }
00285         }
00286         return str2;
00287 }
00288 
00289 
00290 std::string Database::xmlsafestr(const std::string& str)
00291 {
00292         std::string str2;
00293         for (size_t i = 0; i < str.size(); i++)
00294         {
00295                 switch (str[i])
00296                 {
00297                 case '&':
00298                         str2 += "&amp;";
00299                         break;
00300                 case '<':
00301                         str2 += "&lt;";
00302                         break;
00303                 case '>':
00304                         str2 += "&gt;";
00305                         break;
00306                 case '"':
00307                         str2 += "&quot;";
00308                         break;
00309                 case '\'':
00310                         str2 += "&apos;";
00311                         break;
00312                 default:
00313                         str2 += str[i];
00314                 }
00315         }
00316         return str2;
00317 }
00318 
00319 
00320 int64_t Database::a2bigint(const std::string& str)
00321 {
00322         int64_t val = 0;
00323         bool sign = false;
00324         size_t i = 0;
00325         if (str[i] == '-')
00326         {
00327                 sign = true;
00328                 i++;
00329         }
00330         for (; i < str.size(); i++)
00331         {
00332                 val = val * 10 + (str[i] - 48);
00333         }
00334         return sign ? -val : val;
00335 }
00336 
00337 
00338 uint64_t Database::a2ubigint(const std::string& str)
00339 {
00340         uint64_t val = 0;
00341         for (size_t i = 0; i < str.size(); i++)
00342         {
00343                 val = val * 10 + (str[i] - 48);
00344         }
00345         return val;
00346 }
00347 
00348 
00349 #ifdef SQLITEW_NAMESPACE
00350 } // namespace SQLITEW_NAMESPACE {
00351 #endif
00352 
Page, code, and content Copyright (C) 2006 by Anders Hedström