• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

sqlite3x_connection.cpp

00001 /*
00002   Copyright (C) 2004-2005 Cory Nelson
00003   Copyright (C) 2006 stephan beal
00004 
00005   This software is provided 'as-is', without any express or implied
00006   warranty.  In no event will the authors be held liable for any damages
00007   arising from the use of this software.
00008 
00009   Permission is granted to anyone to use this software for any purpose,
00010   including commercial applications, and to alter it and redistribute it
00011   freely, subject to the following restrictions:
00012 
00013   1. The origin of this software must not be misrepresented; you must not
00014   claim that you wrote the original software. If you use this software
00015   in a product, an acknowledgment in the product documentation would be
00016   appreciated but is not required.
00017   2. Altered source versions must be plainly marked as such, and must not be
00018   misrepresented as being the original software.
00019   3. This notice may not be removed or altered from any source distribution.
00020     
00021   Changes made by stephan@s11n.net:
00022 
00023   - Changed ~sqlite3_connection() to use this->close() instead of sqlite3_close().
00024 
00025 */
00026 
00027 #include <sqlite3.h>
00028 #include "sqlite3x.hpp"
00029 
00030 #include <sstream>
00031 #include <vector>
00032 namespace sqlite3x {
00033 
00034     bool rc_is_okay( int rc )
00035     {
00036         return ((SQLITE_DONE==rc) || (SQLITE_OK==rc) || (SQLITE_ROW==rc));
00037     }
00038 
00039     sqlite3_connection::sqlite3_connection() : m_db(NULL), m_name() {}
00040 
00041     sqlite3_connection::sqlite3_connection(std::string const & dbn)
00042         : m_db(NULL), m_name(dbn)
00043     {
00044         this->open(dbn);
00045     }
00046 
00047 #if SQLITE3X_USE_WCHAR
00048     sqlite3_connection::sqlite3_connection(const wchar_t *dbn) : m_db(NULL), m_name() { this->open(dbn); }
00049 #endif
00050 
00051     sqlite3_connection::sqlite3_connection( sqlite3 * dbh )
00052         : m_db(0), m_name()
00053     {
00054         if( ! dbh )
00055         {
00056             throw database_error( "sqlite3_connection(sqlite3*) ctor was passed a null db handle." );
00057         }
00058         this->take( dbh );
00059     }
00060 
00061     sqlite3_connection::~sqlite3_connection()
00062     {
00063         try
00064         {
00065             this->close();
00066         }
00067         catch(...)
00068         {
00069             // ignored for the sake of a no-throw dtor.
00070         }
00071     }
00072 
00073 
00074     void sqlite3_connection::take( sqlite3 * dbh )
00075     {
00076 
00077         if( this->m_db == dbh ) return;
00078         try
00079         {
00080             if( this->m_db || (!dbh) )
00081             {
00082                 this->close();
00083             }
00084             this->m_db = dbh;
00085             if( dbh )
00086             {
00087                 this->on_open();
00088             }
00089         }
00090         catch( ... )
00091         {
00092             this->m_db = dbh;
00093             throw;
00094         }
00095     }
00096 
00097     sqlite3 * sqlite3_connection::take() throw()
00098     {
00099         sqlite3 * ret = this->m_db;
00100         this->m_db = 0;
00101         return ret;
00102     }
00103 
00104     sqlite3 * sqlite3_connection::db() const
00105     {
00106         return this->m_db;
00107     }
00108 
00109     std::string sqlite3_connection::name() const
00110     {
00111         return this->m_name;
00112     }
00113 
00114     std::string sqlite3_connection::errormsg() const
00115     {
00116         char const * m = this->m_db ? sqlite3_errmsg(this->m_db) : "";
00117         return m ? m : "";
00118     }
00119 
00120     void sqlite3_connection::on_open()
00121     {
00122         return;
00123     }
00124     void sqlite3_connection::open( char const * db) {
00125         this->close();
00126         this->m_name = db ? db : "";
00127         if(sqlite3_open(db, &this->m_db)!=SQLITE_OK)
00128             throw database_error("unable to open database %s", db ? db : "<null>");
00129         try
00130         {
00131             // Potential bug: when open() is called from
00132             // the ctor of subclasses as a result of
00133             // calling the parent class ctor, the subclass
00134             // part of the subclass may not be complete,
00135             // and a less derived on_open() may
00136             // potentially be called. ???
00137             this->on_open();
00138         }
00139         catch(...)
00140         {
00141             try { this->close(); }
00142             catch(...) { /* ignore */ }
00143             throw;
00144         }
00145     }
00146 
00147     void sqlite3_connection::open(std::string const & db)
00148     {
00149         return this->open( db.c_str() );
00150     }
00151 
00152 #if SQLITE3X_USE_WCHAR
00153     void sqlite3_connection::open(const wchar_t *db) {
00154         if(sqlite3_open16(db, &this->m_db)!=SQLITE_OK)
00155             throw database_error("unable to open database");
00156         try
00157         {
00158             this->on_open();
00159         }
00160         catch(...)
00161         {
00162             try { this->close(); }
00163             catch(...) { /* ignore */ }
00164             throw;
00165         }
00166     }
00167 #endif
00168 
00169     void sqlite3_connection::close() {
00170         if(this->m_db) {
00171             sqlite3 * x = this->m_db;
00172             this->m_db=NULL;
00173             if(sqlite3_close(x)!=SQLITE_OK)
00174                 throw database_error(*this);
00175         }
00176     }
00177 
00178     int64_t sqlite3_connection::insertid() {
00179         if(!this->m_db) throw database_error("database is not open");
00180         return sqlite3_last_insert_rowid(this->m_db);
00181     }
00182 
00183     int sqlite3_connection::changes() {
00184         if(!this->m_db) throw database_error("database is not open");
00185         return sqlite3_changes(this->m_db);
00186     }
00187 
00188 
00189     void sqlite3_connection::setbusytimeout(int ms) {
00190         if(!this->m_db) throw database_error("database is not open");
00191 
00192         if(sqlite3_busy_timeout(this->m_db, ms)!=SQLITE_OK)
00193             throw database_error(*this);
00194     }
00195 
00196     void sqlite3_connection::executenonquery(const std::string &sql) {
00197         this->executenonquery( sql.c_str() );
00198     }
00199 
00200     void sqlite3_connection::executenonquery(char const * sql) {
00201         if(!this->m_db) throw database_error("database is not open");
00202         sqlite3_command(*this, sql).executenonquery();
00203     }
00204 
00205 #if SQLITE3X_USE_WCHAR
00206     void sqlite3_connection::executenonquery(const std::wstring &sql) {
00207         if(!this->m_db) throw database_error("database is not open");
00208         sqlite3_command(*this, sql).executenonquery();
00209     }
00210 #endif
00211 
00212     int sqlite3_connection::executeint(char const * sql) {
00213         if(!this->m_db) throw database_error("database is not open");
00214         return sqlite3_command(*this, sql).executeint();
00215     }
00216     int sqlite3_connection::executeint(const std::string &sql) {
00217         return this->executeint( sql.c_str() );
00218     }
00219 
00220 #if SQLITE3X_USE_WCHAR
00221     int sqlite3_connection::executeint(const std::wstring &sql) {
00222         if(!this->m_db) throw database_error("database is not open");
00223         return sqlite3_command(*this, sql).executeint();
00224     }
00225 #endif
00226 
00227     int64_t sqlite3_connection::executeint64(char const  * sql) {
00228         if(!this->m_db) throw database_error("database is not open");
00229         return sqlite3_command(*this, sql).executeint64();
00230     }
00231 
00232     int64_t sqlite3_connection::executeint64(const std::string &sql) {
00233         return this->executeint64( sql.c_str() );
00234     }
00235 
00236 #if SQLITE3X_USE_WCHAR
00237     int64_t sqlite3_connection::executeint64(const std::wstring &sql) {
00238         if(!this->m_db) throw database_error("database is not open");
00239         return sqlite3_command(*this, sql).executeint64();
00240     }
00241 #endif
00242 
00243     double sqlite3_connection::executedouble(char const * sql) {
00244         if(!this->m_db) throw database_error("database is not open");
00245         return sqlite3_command(*this, sql).executedouble();
00246     }
00247 
00248     double sqlite3_connection::executedouble(const std::string &sql) {
00249         return this->executedouble( sql.c_str() );
00250     }
00251 
00252 #if SQLITE3X_USE_WCHAR
00253     double sqlite3_connection::executedouble(const std::wstring &sql) {
00254         if(!this->m_db) throw database_error("database is not open");
00255         return sqlite3_command(*this, sql).executedouble();
00256     }
00257 #endif
00258 
00259     std::string sqlite3_connection::executestring(const std::string &sql) {
00260         if(!this->m_db) throw database_error("database is not open");
00261         return sqlite3_command(*this, sql).executestring();
00262     }
00263 
00264 #if SQLITE3X_USE_WCHAR
00265     std::string sqlite3_connection::executestring(const std::wstring &sql) {
00266         if(!this->m_db) throw database_error("database is not open");
00267         return sqlite3_command(*this, sql).executestring();
00268     }
00269 #endif
00270 
00271 #if SQLITE3X_USE_WCHAR
00272     std::wstring sqlite3_connection::executestring16(const std::string &sql) {
00273         if(!this->m_db) throw database_error("database is not open");
00274         return sqlite3_command(*this, sql).executestring16();
00275     }
00276 #endif
00277 
00278 #if SQLITE3X_USE_WCHAR
00279     std::wstring sqlite3_connection::executestring16(const std::wstring &sql) {
00280         if(!this->m_db) throw database_error("database is not open");
00281         return sqlite3_command(*this, sql).executestring16();
00282     }
00283 #endif
00284 
00285     std::string sqlite3_connection::executeblob(const std::string &sql) {
00286         if(!this->m_db) throw database_error("database is not open");
00287         return sqlite3_command(*this, sql).executeblob();
00288     }
00289 
00290 #if SQLITE3X_USE_WCHAR
00291     std::string sqlite3_connection::executeblob(const std::wstring &sql) {
00292         if(!this->m_db) throw database_error("database is not open");
00293         return sqlite3_command(*this, sql).executeblob();
00294     }
00295 #endif
00296     
00297     int sqlite3_connection::executecallback( std::string const & sql,
00298                          sqlite3_callback callback,
00299                          void * data,
00300                          std::string & errmsg )
00301     {
00302         char * cerrmsg = 0;
00303         int ret = 0;
00304         try
00305         {
00306             // allow callback to safely throw.
00307             ret = sqlite3_exec( this->m_db, sql.c_str(), callback, data, &cerrmsg );
00308         }
00309         catch( ... )
00310         {
00311             if( cerrmsg )
00312             {
00313                 errmsg = cerrmsg;
00314                 sqlite3_free( cerrmsg );
00315             }
00316             throw;
00317         }
00318         if( cerrmsg )
00319         {
00320             errmsg = cerrmsg;
00321             sqlite3_free( cerrmsg );
00322         }
00323         return ret;
00324     }
00325 
00326     int sqlite3_connection::executecallback( std::string const & sql,
00327                          sqlite3_callback func,
00328                          void * data )
00329     {
00330         std::string ignored;
00331         return this->executecallback( sql, func, data, ignored );
00332     }
00333 
00334     /**
00335        An internal implementation detail of table_generator.
00336     */
00337     class table_generator::table_generator_impl
00338     {
00339 
00340     public:
00341         sqlite3_connection * db;
00342         std::string name;
00343         std::vector<std::string> list;
00344     };
00345 
00346 //  int sqlite3_function_info8::create( sqlite3 * db )
00347 //  {
00348 //      return sqlite3_create_function(
00349 //                         db,
00350 //                         this->name,
00351 //                         this->argc,
00352 //                         0,
00353 //                         this->user_data,
00354 //                         this->func,
00355 //                         this->step,
00356 //                         this->final );
00357 //  }
00358 
00359 //  int sqlite3_function_info16::create( sqlite3 * db )
00360 //  {
00361 //      return sqlite3_create_function16(
00362 //                         db,
00363 //                         this->name,
00364 //                         this->argc,
00365 //                         1,
00366 //                         this->user_data,
00367 //                         this->func,
00368 //                         this->step,
00369 //                         this->final );
00370 //  }
00371 
00372     table_generator::table_generator( sqlite3_connection & con, std::string const & n )
00373         : m_pimpl( new table_generator::table_generator_impl )
00374     {
00375         int check = con.executeint( "select count(*) from sqlite_master where type like 'table' and name like '"+n+"'" );
00376         // ^^^ we use 'like' here because sqlite3 is case-insensitive
00377         if( 0 != check )
00378         {
00379             throw database_error( "table_generator() db table '%s' already exists.", n.c_str() );
00380         }
00381         this->m_pimpl->db = &con;
00382         this->m_pimpl->name = n;
00383     }
00384 
00385     table_generator::~table_generator() throw()
00386     {
00387         delete this->m_pimpl;
00388     }
00389 
00390     table_generator & table_generator::operator()( std::string const & fld )
00391     {
00392         this->m_pimpl->list.push_back( fld );
00393         return *this;
00394     }
00395 
00396     void table_generator::create()
00397     {
00398         size_t sz = this->m_pimpl->list.size();
00399         if( ! sz )
00400         {
00401             throw database_error( "table_generator::operator(): cannot create a table with no fields. Try using operator()(string) to add fields." );
00402         }
00403         std::ostringstream os;
00404         os << "create table "<< this->m_pimpl->name << "(";
00405         for( size_t i = 0; i < sz; ++i )
00406         {
00407             os << this->m_pimpl->list[i];
00408             if( i < (sz-1) ) os << ",";
00409         }
00410         os << ");";
00411         this->m_pimpl->db->executenonquery( os.str() );
00412     }
00413 
00414 }

Generated on Tue Jan 4 2011 for libsqlite3x by  doxygen 1.7.1