00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00132
00133
00134
00135
00136
00137 this->on_open();
00138 }
00139 catch(...)
00140 {
00141 try { this->close(); }
00142 catch(...) { }
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(...) { }
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
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
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
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
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
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 }