Skip to content

Commit 186d087

Browse files
authored
Merge pull request #54 from aminroosta/exceptions
fix exceptions
2 parents fb52ef4 + 18f61c6 commit 186d087

File tree

3 files changed

+106
-60
lines changed

3 files changed

+106
-60
lines changed

Diff for: README.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@ It is possible to retain and reuse statments this will keep the query plan and i
9999
ps >> [&](int a,int b){ ... };
100100

101101
// after a successfull execution the statment needs to be reset to be execute again. This will reset the bound values too!
102-
ps->reset();
102+
ps.reset();
103103

104104
// If you dont need the returned values you can execute it like this
105-
ps->execute(); // the statment will not be reset!
105+
ps.execute(); // the statment will not be reset!
106106

107107
// there is a convinience operator to execute and reset in one go
108108
ps++;
109109

110110
// To disable the execution of a statment when it goes out of scope and wasn't used
111-
ps->used(true); // or false if you want it to execute even if it was used
111+
ps.used(true); // or false if you want it to execute even if it was used
112112

113113
// Usage Example:
114114

@@ -153,7 +153,6 @@ Take this example on how to deal with a database backup using SQLITEs own functi
153153
Transactions
154154
=====
155155
You can use transactions with `begin;`, `commit;` and `rollback;` commands.
156-
*(don't forget to put all the semicolons at the end of each query)*.
157156

158157
```c++
159158
db << "begin;"; // begin a transaction ...
@@ -286,7 +285,28 @@ Errors
286285
287286
On error, the library throws an error class indicating the type of error. The error classes are derived from the SQLITE3 error names, so if the error code is SQLITE_CONSTRAINT, the error class thrown is sqlite::exceptions::constraint. Note that all errors are derived from sqlite::sqlite_exception and that itself is derived from std::runtime_exception.
288287
289-
*node: for NDK use the full path to your database file : `sqlite::database db("/data/data/com.your.package/dbfile.db")`*.
288+
```c++
289+
database db(":memory:");
290+
db << "create table person (id integer primary key not null, name text);";
291+
292+
try {
293+
db << "insert into person (id, name) values (?,?)" << 1 << "jack";
294+
// inserting again to produce error
295+
db << "insert into person (id, name) values (?,?)" << 1 << "jack";
296+
}
297+
/* if you are trying to catch all sqlite related exceptions
298+
* make sure to catch them by reference */
299+
catch (sqlite_exception& e) {
300+
cerr << e.what() << endl;
301+
}
302+
/* you can catch specific exceptions as well,
303+
catch(sqlite::exceptions::constraint e) { } */
304+
```
305+
306+
NDK support
307+
======
308+
Just Make sure you are using the full path of your database file :
309+
`sqlite::database db("/data/data/com.your.package/dbfile.db")`.
290310

291311
Building and Installing
292312
=====

Diff for: hdr/sqlite_modern_cpp.h

+49-55
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ namespace sqlite {
116116
class database_binder {
117117

118118
public:
119-
typedef std::unique_ptr<sqlite::database_binder> chain_type;
119+
database_binder(database_binder&& other) = default;
120+
// database_binder is not copyable
121+
database_binder() = delete;
122+
database_binder(const database_binder& other) = delete;
123+
database_binder& operator=(const database_binder&) = delete;
124+
120125

121126
void reset() {
122127
sqlite3_reset(_stmt.get());
@@ -208,30 +213,23 @@ namespace sqlite {
208213
> { };
209214

210215

211-
template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const T& val);
216+
template<typename T> friend database_binder& operator <<(database_binder& db, const T& val);
212217
template<typename T> friend void get_col_from_db(database_binder& db, int inx, T& val);
213218
/* for vector<T> support */
214-
template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::vector<T>& val);
219+
template<typename T> friend database_binder& operator <<(database_binder& db, const std::vector<T>& val);
215220
template<typename T> friend void get_col_from_db(database_binder& db, int inx, std::vector<T>& val);
216221
/* for nullptr & unique_ptr support */
217-
friend database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t);
218-
template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr<T>& val);
222+
friend database_binder& operator <<(database_binder& db, std::nullptr_t);
223+
template<typename T> friend database_binder& operator <<(database_binder& db, const std::unique_ptr<T>& val);
219224
template<typename T> friend void get_col_from_db(database_binder& db, int inx, std::unique_ptr<T>& val);
220225
template<typename T> friend T operator++(database_binder& db, int);
221226

222227

223228
#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
224-
template <typename BoostOptionalT> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const boost::optional<BoostOptionalT>& val);
229+
template <typename BoostOptionalT> friend database_binder& operator <<(database_binder& db, const boost::optional<BoostOptionalT>& val);
225230
template <typename BoostOptionalT> friend void get_col_from_db(database_binder& db, int inx, boost::optional<BoostOptionalT>& o);
226231
#endif
227232

228-
229-
database_binder() = delete;
230-
database_binder(const database_binder& other) = delete;
231-
database_binder& operator=(const database_binder&) = delete;
232-
database_binder(const database_binder&& other) = delete;
233-
234-
235233
public:
236234

237235
database_binder(std::shared_ptr<sqlite3> db, std::u16string const & sql):
@@ -299,19 +297,19 @@ namespace sqlite {
299297
database(std::shared_ptr<sqlite3> db):
300298
_db(db) {}
301299

302-
database_binder::chain_type operator<<(const std::string& sql) {
303-
return database_binder::chain_type(new database_binder(_db, sql));
300+
database_binder operator<<(const std::string& sql) {
301+
return database_binder(_db, sql);
304302
}
305303

306-
database_binder::chain_type operator<<(const char* sql) {
304+
database_binder operator<<(const char* sql) {
307305
return *this << std::string(sql);
308306
}
309307

310-
database_binder::chain_type operator<<(const std::u16string& sql) {
311-
return database_binder::chain_type(new database_binder(_db, sql));
308+
database_binder operator<<(const std::u16string& sql) {
309+
return database_binder(_db, sql);
312310
}
313311

314-
database_binder::chain_type operator<<(const char16_t* sql) {
312+
database_binder operator<<(const char16_t* sql) {
315313
return *this << std::u16string(sql);
316314
}
317315

@@ -372,12 +370,12 @@ namespace sqlite {
372370
};
373371

374372
// int
375-
template<> inline database_binder::chain_type& operator<<(database_binder::chain_type& db, const int& val) {
373+
template<> inline database_binder& operator<<(database_binder& db, const int& val) {
376374
int hresult;
377-
if((hresult = sqlite3_bind_int(db->_stmt.get(), db->_inx, val)) != SQLITE_OK) {
375+
if((hresult = sqlite3_bind_int(db._stmt.get(), db._inx, val)) != SQLITE_OK) {
378376
exceptions::throw_sqlite_error(hresult);
379377
}
380-
++db->_inx;
378+
++db._inx;
381379
return db;
382380
}
383381
template<> inline void get_col_from_db(database_binder& db, int inx, int& val) {
@@ -389,13 +387,13 @@ namespace sqlite {
389387
}
390388

391389
// sqlite_int64
392-
template<> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const sqlite_int64& val) {
390+
template<> inline database_binder& operator <<(database_binder& db, const sqlite_int64& val) {
393391
int hresult;
394-
if((hresult = sqlite3_bind_int64(db->_stmt.get(), db->_inx, val)) != SQLITE_OK) {
392+
if((hresult = sqlite3_bind_int64(db._stmt.get(), db._inx, val)) != SQLITE_OK) {
395393
exceptions::throw_sqlite_error(hresult);
396394
}
397395

398-
++db->_inx;
396+
++db._inx;
399397
return db;
400398
}
401399
template<> inline void get_col_from_db(database_binder& db, int inx, sqlite3_int64& i) {
@@ -407,13 +405,13 @@ namespace sqlite {
407405
}
408406

409407
// float
410-
template<> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const float& val) {
408+
template<> inline database_binder& operator <<(database_binder& db, const float& val) {
411409
int hresult;
412-
if((hresult = sqlite3_bind_double(db->_stmt.get(), db->_inx, double(val))) != SQLITE_OK) {
410+
if((hresult = sqlite3_bind_double(db._stmt.get(), db._inx, double(val))) != SQLITE_OK) {
413411
exceptions::throw_sqlite_error(hresult);
414412
}
415413

416-
++db->_inx;
414+
++db._inx;
417415
return db;
418416
}
419417
template<> inline void get_col_from_db(database_binder& db, int inx, float& f) {
@@ -425,13 +423,13 @@ namespace sqlite {
425423
}
426424

427425
// double
428-
template<> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const double& val) {
426+
template<> inline database_binder& operator <<(database_binder& db, const double& val) {
429427
int hresult;
430-
if((hresult = sqlite3_bind_double(db->_stmt.get(), db->_inx, val)) != SQLITE_OK) {
428+
if((hresult = sqlite3_bind_double(db._stmt.get(), db._inx, val)) != SQLITE_OK) {
431429
exceptions::throw_sqlite_error(hresult);
432430
}
433431

434-
++db->_inx;
432+
++db._inx;
435433
return db;
436434
}
437435
template<> inline void get_col_from_db(database_binder& db, int inx, double& d) {
@@ -443,14 +441,14 @@ namespace sqlite {
443441
}
444442

445443
// vector<T>
446-
template<typename T> inline database_binder::chain_type& operator<<(database_binder::chain_type& db, const std::vector<T>& vec) {
444+
template<typename T> inline database_binder& operator<<(database_binder& db, const std::vector<T>& vec) {
447445
void const* buf = reinterpret_cast<void const *>(vec.data());
448446
int bytes = vec.size() * sizeof(T);
449447
int hresult;
450-
if((hresult = sqlite3_bind_blob(db->_stmt.get(), db->_inx, buf, bytes, SQLITE_TRANSIENT)) != SQLITE_OK) {
448+
if((hresult = sqlite3_bind_blob(db._stmt.get(), db._inx, buf, bytes, SQLITE_TRANSIENT)) != SQLITE_OK) {
451449
exceptions::throw_sqlite_error(hresult);
452450
}
453-
++db->_inx;
451+
++db._inx;
454452
return db;
455453
}
456454
template<typename T> inline void get_col_from_db(database_binder& db, int inx, std::vector<T>& vec) {
@@ -464,16 +462,16 @@ namespace sqlite {
464462
}
465463

466464
/* for nullptr support */
467-
inline database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t) {
465+
inline database_binder& operator <<(database_binder& db, std::nullptr_t) {
468466
int hresult;
469-
if((hresult = sqlite3_bind_null(db->_stmt.get(), db->_inx)) != SQLITE_OK) {
467+
if((hresult = sqlite3_bind_null(db._stmt.get(), db._inx)) != SQLITE_OK) {
470468
exceptions::throw_sqlite_error(hresult);
471469
}
472-
++db->_inx;
470+
++db._inx;
473471
return db;
474472
}
475473
/* for nullptr support */
476-
template<typename T> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr<T>& val) {
474+
template<typename T> inline database_binder& operator <<(database_binder& db, const std::unique_ptr<T>& val) {
477475
if(val)
478476
db << *val;
479477
else
@@ -503,16 +501,16 @@ namespace sqlite {
503501
}
504502

505503
// Convert char* to string to trigger op<<(..., const std::string )
506-
template<std::size_t N> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const char(&STR)[N]) { return db << std::string(STR); }
507-
template<std::size_t N> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const char16_t(&STR)[N]) { return db << std::u16string(STR); }
504+
template<std::size_t N> inline database_binder& operator <<(database_binder& db, const char(&STR)[N]) { return db << std::string(STR); }
505+
template<std::size_t N> inline database_binder& operator <<(database_binder& db, const char16_t(&STR)[N]) { return db << std::u16string(STR); }
508506

509-
template<> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::string& txt) {
507+
template<> inline database_binder& operator <<(database_binder& db, const std::string& txt) {
510508
int hresult;
511-
if((hresult = sqlite3_bind_text(db->_stmt.get(), db->_inx, txt.data(), -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
509+
if((hresult = sqlite3_bind_text(db._stmt.get(), db._inx, txt.data(), -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
512510
exceptions::throw_sqlite_error(hresult);
513511
}
514512

515-
++db->_inx;
513+
++db._inx;
516514
return db;
517515
}
518516
// std::u16string
@@ -526,27 +524,27 @@ namespace sqlite {
526524
}
527525

528526

529-
template<> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::u16string& txt) {
527+
template<> inline database_binder& operator <<(database_binder& db, const std::u16string& txt) {
530528
int hresult;
531-
if((hresult = sqlite3_bind_text16(db->_stmt.get(), db->_inx, txt.data(), -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
529+
if((hresult = sqlite3_bind_text16(db._stmt.get(), db._inx, txt.data(), -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
532530
exceptions::throw_sqlite_error(hresult);
533531
}
534532

535-
++db->_inx;
533+
++db._inx;
536534
return db;
537535
}
538536
// boost::optinal support for NULL values
539537
#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
540-
template <typename BoostOptionalT> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const boost::optional<BoostOptionalT>& val) {
538+
template <typename BoostOptionalT> inline database_binder& operator <<(database_binder& db, const boost::optional<BoostOptionalT>& val) {
541539
if(val) {
542540
return operator << (std::move(db), std::move(*val));
543541
}
544542
int hresult;
545-
if((hresult = sqlite3_bind_null(db->_stmt.get(), db->_inx)) != SQLITE_OK) {
543+
if((hresult = sqlite3_bind_null(db._stmt.get(), db._inx)) != SQLITE_OK) {
546544
exceptions::throw_sqlite_error(hresult);
547545
}
548546

549-
++db->_inx;
547+
++db._inx;
550548
return db;
551549
}
552550

@@ -561,14 +559,10 @@ namespace sqlite {
561559
}
562560
#endif
563561

564-
// there is too much magic here, val might be rValue or lValue
565-
template<typename T> void operator >> (database_binder::chain_type& db, T&& val) { *db >> std::forward<T>(val); }
566-
template<typename T> void operator >> (database_binder::chain_type&& db, T&& val) { db >> std::forward<T>(val); }
567-
568562
// Some ppl are lazy so we have a operator for proper prep. statemant handling.
569-
void inline operator++(database_binder::chain_type& db, int) { db->execute(); db->reset(); }
563+
void inline operator++(database_binder& db, int) { db.execute(); db.reset(); }
570564

571565
// Convert the rValue binder to a reference and call first op<<, its needed for the call that creates the binder (be carfull of recursion here!)
572-
template<typename T> database_binder::chain_type& operator << (database_binder::chain_type&& db, const T& val) { return db << val; }
566+
template<typename T> database_binder& operator << (database_binder&& db, const T& val) { return db << val; }
573567

574568
}

Diff for: tests/exceptions.cc

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <memory>
4+
#include <stdexcept>
5+
#include <sqlite_modern_cpp.h>
6+
using namespace sqlite;
7+
using namespace std;
8+
9+
10+
int main() {
11+
database db(":memory:");
12+
db << "CREATE TABLE person (id integer primary key not null, name TEXT);";
13+
bool expception_thrown = false;
14+
15+
try {
16+
db << "INSERT INTO person (id,name) VALUES (?,?)" << 1 << "jack";
17+
// inserting again to produce error
18+
db << "INSERT INTO person (id,name) VALUES (?,?)" << 1 << "jack";
19+
} catch (sqlite_exception& e) {
20+
cerr << e.what() << endl;
21+
expception_thrown = true;
22+
} catch (...) {
23+
cerr << "Ok, we have our excpetion thrown" << endl;
24+
expception_thrown = true;
25+
}
26+
27+
if(!expception_thrown) {
28+
exit(EXIT_FAILURE);
29+
}
30+
31+
exit(EXIT_SUCCESS);
32+
}

0 commit comments

Comments
 (0)