Skip to content

Commit

Permalink
Merge pull request #52 from aminroosta/nullptr
Browse files Browse the repository at this point in the history
support nullptr and uniqueptr, fixes #48
  • Loading branch information
aminroosta committed May 6, 2016
2 parents 67d00e8 + 9239b75 commit fb52ef4
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 2 deletions.
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,43 @@ Use `std::vector<T>` 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<T>` 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<int> { 1, 2 , 3};
unique_ptr<string> ptr_null; // you can even bind empty unique_ptr<T>
db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr;
db << "select age,name,img from tbl where id = 1"
>> [](unique_ptr<int> age_p, unique_ptr<string> name_p, unique_ptr<vector<int>> 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<int> age_p, unique_ptr<string> name_p, unique_ptr<vector<int>> 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 <sqlite_modern_cpp.h>

Expand Down
34 changes: 34 additions & 0 deletions hdr/sqlite_modern_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,13 @@ namespace sqlite {

template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const T& val);
template<typename T> friend void get_col_from_db(database_binder& db, int inx, T& val);
/* for vector<T> support */
template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::vector<T>& val);
template<typename T> friend void get_col_from_db(database_binder& db, int inx, std::vector<T>& val);
/* for nullptr & unique_ptr support */
friend database_binder::chain_type& operator <<(database_binder::chain_type& db, std::nullptr_t);
template<typename T> friend database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr<T>& val);
template<typename T> friend void get_col_from_db(database_binder& db, int inx, std::unique_ptr<T>& val);
template<typename T> friend T operator++(database_binder& db, int);


Expand Down Expand Up @@ -458,6 +463,35 @@ 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 nullptr support */
template<typename T> inline database_binder::chain_type& operator <<(database_binder::chain_type& db, const std::unique_ptr<T>& val) {
if(val)
db << *val;
else
db << nullptr;
return db;
}

/* for unique_ptr<T> support */
template<typename T> inline void get_col_from_db(database_binder& db, int inx, std::unique_ptr<T>& _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) {
Expand Down
47 changes: 47 additions & 0 deletions tests/nullptr_uniqueptr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <iostream>
#include <string>
#include <vector>
#include <sqlite_modern_cpp.h>
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<int> { 1, 2 , 3};
unique_ptr<string> ptr_null;
db << "INSERT INTO tbl VALUES (?, ?, ?, ?);" << 2 << nullptr << ptr_null << nullptr;

db << "select age,name,img from tbl where id = 1" >> [](unique_ptr<int> age_p, unique_ptr<string> name_p, unique_ptr<vector<int>> 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<int> age_p, unique_ptr<string> name_p, unique_ptr<vector<int>> 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;
}

0 comments on commit fb52ef4

Please sign in to comment.