From 69388a0c63ef36d2c88e08a0f6e8740aea4409d3 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Fri, 6 May 2016 19:25:18 +0430 Subject: [PATCH 1/4] support nullptr and uniqueptr --- hdr/sqlite_modern_cpp.h | 25 +++++++++++++++++++++ tests/nullptr_uniqueptr.cc | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tests/nullptr_uniqueptr.cc diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 49ba5b57..13e5b0c8 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -210,8 +210,12 @@ namespace sqlite { template friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const T& val); template friend void get_col_from_db(database_binder& db, int inx, T& val); + /* for vector support */ template friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::vector& val); template friend void get_col_from_db(database_binder& db, int inx, std::vector& val); + /* for nullptr & unique_ptr support */ + friend database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t); + template friend void get_col_from_db(database_binder& db, int inx, std::unique_ptr& val); template friend T operator++(database_binder& db, int); @@ -458,6 +462,27 @@ namespace sqlite { } } + /* for nullptr support */ + inline database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t) { + int hresult; + if((hresult = sqlite3_bind_null(db->_stmt.get(), db->_inx)) != SQLITE_OK) { + exceptions::throw_sqlite_error(hresult); + } + ++db->_inx; + return db; + } + + /* for unique_ptr support */ + template inline void get_col_from_db(database_binder& db, int inx, std::unique_ptr& _ptr_) { + if(sqlite3_column_type(db._stmt.get(), inx) == SQLITE_NULL) { + _ptr_ = nullptr; + } else { + auto underling_ptr = new T(); + get_col_from_db(db, inx, *underling_ptr); + _ptr_.reset(underling_ptr); + } + } + // std::string template<> inline void get_col_from_db(database_binder& db, int inx, std::string & s) { if(sqlite3_column_type(db._stmt.get(), inx) == SQLITE_NULL) { diff --git a/tests/nullptr_uniqueptr.cc b/tests/nullptr_uniqueptr.cc new file mode 100644 index 00000000..1bda36b6 --- /dev/null +++ b/tests/nullptr_uniqueptr.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +using namespace std; +using namespace sqlite; + +int main() { + + try { + database db(":memory:"); + db << "CREATE TABLE tbl (id integer,age integer, name string, img blob);"; + db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 1 << 24 << "bob" << vector { 1, 2 , 3}; + db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << nullptr << nullptr; + + db << "select age,name,img from tbl where id = 1" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + if(age_p == nullptr || name_p == nullptr || img_p == nullptr) { + cerr << "ERROR: values should not be null" << std::endl; + exit(EXIT_FAILURE); + } + + cout << "age:" << *age_p << " name:" << *name_p << " img:"; + for(auto i : *img_p) cout << i << ","; cout << endl; + }; + + db << "select age,name,img from tbl where id = 2" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + if(age_p != nullptr || name_p != nullptr || img_p != nullptr) { + cerr << "ERROR: values should be nullptr" << std::endl; + exit(EXIT_FAILURE); + } + + cout << "OK all three values are nullptr" << endl; + }; + + } catch(sqlite_exception e) { + cout << "Sqlite error " << e.what() << endl; + exit(EXIT_FAILURE); + } catch(...) { + cout << "Unknown error\n"; + exit(EXIT_FAILURE); + } + + cout << "OK\n"; + exit(EXIT_SUCCESS); + return 0; +} From 686b7185d088cf988926ab4d44166cb6a02e1f9b Mon Sep 17 00:00:00 2001 From: amin roosta Date: Fri, 6 May 2016 19:32:27 +0430 Subject: [PATCH 2/4] support uniqeptr as input arguments --- hdr/sqlite_modern_cpp.h | 9 +++++++++ tests/nullptr_uniqueptr.cc | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 13e5b0c8..6a864a50 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -215,6 +215,7 @@ namespace sqlite { template friend void get_col_from_db(database_binder& db, int inx, std::vector& val); /* for nullptr & unique_ptr support */ friend database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t); + template friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr& val); template friend void get_col_from_db(database_binder& db, int inx, std::unique_ptr& val); template friend T operator++(database_binder& db, int); @@ -471,6 +472,14 @@ namespace sqlite { ++db->_inx; return db; } + /* for nullptr support */ + template inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr& val) { + if(val) + db << *val; + else + db << nullptr; + return db; + } /* for unique_ptr support */ template inline void get_col_from_db(database_binder& db, int inx, std::unique_ptr& _ptr_) { diff --git a/tests/nullptr_uniqueptr.cc b/tests/nullptr_uniqueptr.cc index 1bda36b6..3db96c91 100644 --- a/tests/nullptr_uniqueptr.cc +++ b/tests/nullptr_uniqueptr.cc @@ -11,7 +11,8 @@ int main() { database db(":memory:"); db << "CREATE TABLE tbl (id integer,age integer, name string, img blob);"; db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 1 << 24 << "bob" << vector { 1, 2 , 3}; - db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << nullptr << nullptr; + unique_ptr ptr_null; + db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr; db << "select age,name,img from tbl where id = 1" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { if(age_p == nullptr || name_p == nullptr || img_p == nullptr) { From e30408b646de81e6bb4d42786bd9e824ccd65ea7 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Fri, 6 May 2016 19:50:19 +0430 Subject: [PATCH 3/4] reformat the test --- tests/nullptr_uniqueptr.cc | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/nullptr_uniqueptr.cc b/tests/nullptr_uniqueptr.cc index 3db96c91..7bc193ae 100644 --- a/tests/nullptr_uniqueptr.cc +++ b/tests/nullptr_uniqueptr.cc @@ -7,14 +7,14 @@ using namespace sqlite; int main() { - try { - database db(":memory:"); - db << "CREATE TABLE tbl (id integer,age integer, name string, img blob);"; - db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 1 << 24 << "bob" << vector { 1, 2 , 3}; + try { + database db(":memory:"); + db << "CREATE TABLE tbl (id integer,age integer, name string, img blob);"; + db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 1 << 24 << "bob" << vector { 1, 2 , 3}; unique_ptr ptr_null; - db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr; + db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr; - db << "select age,name,img from tbl where id = 1" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + db << "select age,name,img from tbl where id = 1" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { if(age_p == nullptr || name_p == nullptr || img_p == nullptr) { cerr << "ERROR: values should not be null" << std::endl; exit(EXIT_FAILURE); @@ -22,26 +22,26 @@ int main() { cout << "age:" << *age_p << " name:" << *name_p << " img:"; for(auto i : *img_p) cout << i << ","; cout << endl; - }; + }; - db << "select age,name,img from tbl where id = 2" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + db << "select age,name,img from tbl where id = 2" >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { if(age_p != nullptr || name_p != nullptr || img_p != nullptr) { cerr << "ERROR: values should be nullptr" << std::endl; exit(EXIT_FAILURE); } cout << "OK all three values are nullptr" << endl; - }; - - } catch(sqlite_exception e) { - cout << "Sqlite error " << e.what() << endl; - exit(EXIT_FAILURE); - } catch(...) { - cout << "Unknown error\n"; - exit(EXIT_FAILURE); - } - - cout << "OK\n"; - exit(EXIT_SUCCESS); + }; + + } catch(sqlite_exception e) { + cout << "Sqlite error " << e.what() << endl; + exit(EXIT_FAILURE); + } catch(...) { + cout << "Unknown error\n"; + exit(EXIT_FAILURE); + } + + cout << "OK\n"; + exit(EXIT_SUCCESS); return 0; } From 9239b755bc9ab8dcda133fcbe913a149d4e4c3f1 Mon Sep 17 00:00:00 2001 From: amin roosta Date: Sat, 7 May 2016 00:34:52 +0430 Subject: [PATCH 4/4] updated readme --- README.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f1d1d8f..cbe16938 100644 --- a/README.md +++ b/README.md @@ -194,12 +194,43 @@ Use `std::vector` to store and retrieve blob data. }; ``` -Dealing with NULL values +NULL values ===== -If you have databases where some rows may be null, you can use boost::optional to retain the NULL value between C++ variables and the database. Note that you must enable the boost support by defining _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT befor importing the header. +If you have databases where some rows may be null, you can use `std::unique_ptr` to retain the NULL values between C++ variables and the database. ```c++ +db << "CREATE TABLE tbl (id integer,age integer, name string, img blob);"; +db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 1 << 24 << "bob" << vector { 1, 2 , 3}; +unique_ptr ptr_null; // you can even bind empty unique_ptr +db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr; + +db << "select age,name,img from tbl where id = 1" + >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + if(age_p == nullptr || name_p == nullptr || img_p == nullptr) { + cerr << "ERROR: values should not be null" << std::endl; + } + + cout << "age:" << *age_p << " name:" << *name_p << " img:"; + for(auto i : *img_p) cout << i << ","; cout << endl; + }; + +db << "select age,name,img from tbl where id = 2" + >> [](unique_ptr age_p, unique_ptr name_p, unique_ptr> img_p) { + if(age_p != nullptr || name_p != nullptr || img_p != nullptr) { + cerr << "ERROR: values should be nullptr" << std::endl; + exit(EXIT_FAILURE); + } + + cout << "OK all three values are nullptr" << endl; + }; +``` + +NULL values (DEPRICATED) +===== +**Note: this option is deprecated and will be removed in future versions.** +You can enable boost support by defining _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT before importing sqlite_modern_cpp header. +```c++ #define _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT #include