From 8342447e3735e5c25171b73131f9e45478aae028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Tue, 31 Jan 2017 00:17:22 +0100 Subject: [PATCH 1/3] Add support for std::optional --- hdr/sqlite_modern_cpp.h | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 3b346f96..f74b085b 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -8,6 +8,10 @@ #include #include +#if __has_include() +#include +#endif + #ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT #include #endif @@ -237,6 +241,11 @@ namespace sqlite { friend database_binder& operator <<(database_binder& db, const std::u16string& txt); +#if __has_include() + template friend database_binder& operator <<(database_binder& db, const std::optional& val); + template friend void get_col_from_db(database_binder& db, int inx, std::optional& o); +#endif + #ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT template friend database_binder& operator <<(database_binder& db, const boost::optional& val); template friend void get_col_from_db(database_binder& db, int inx, boost::optional& o); @@ -545,7 +554,33 @@ namespace sqlite { ++db._inx; return db; } - // boost::optinal support for NULL values + // std::optional support for NULL values +#if __has_include() + template inline database_binder& operator <<(database_binder& db, const std::optional& val) { + if(val) { + return operator << (std::move(db), std::move(*val)); + } + int hresult; + if((hresult = sqlite3_bind_null(db._stmt.get(), db._inx)) != SQLITE_OK) { + exceptions::throw_sqlite_error(hresult); + } + + ++db._inx; + return db; + } + + template inline void get_col_from_db(database_binder& db, int inx, std::optional& o) { + if(sqlite3_column_type(db._stmt.get(), inx) == SQLITE_NULL) { + o.reset(); + } else { + OptionalT v; + get_col_from_db(db, inx, v); + o = std::move(v); + } + } +#endif + + // boost::optional support for NULL values #ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT template inline database_binder& operator <<(database_binder& db, const boost::optional& val) { if(val) { @@ -574,7 +609,7 @@ namespace sqlite { // Some ppl are lazy so we have a operator for proper prep. statemant handling. void inline operator++(database_binder& db, int) { db.execute(); db.reset(); } - // 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!) + // Convert the rValue binder to a reference and call first op<<, its needed for the call that creates the binder (be carefull of recursion here!) template database_binder& operator << (database_binder&& db, const T& val) { return db << val; } } From 48757b5b81333d1790c4be50187f8f6c788ca5ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Tue, 31 Jan 2017 00:38:19 +0100 Subject: [PATCH 2/3] Test for std::optional --- tests/std_optional.cc | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/std_optional.cc diff --git a/tests/std_optional.cc b/tests/std_optional.cc new file mode 100644 index 00000000..64912db2 --- /dev/null +++ b/tests/std_optional.cc @@ -0,0 +1,68 @@ +#include +#include + +#include + +using namespace sqlite; +using namespace std; + +void insert(database& db, bool is_null) { + int id = 1; + std::optional val; + if(!is_null) val = 5; + + db << "delete from test where id = 1"; + db << "insert into test(id,val) values(?,?)" << id << val; +} + +void select(database& db, bool should_be_null) { + db << "select id,val from test" >> [&](long long, std::optional val) { + if(should_be_null) { + if(val) exit(EXIT_FAILURE); + } else { + if(!val) exit(EXIT_FAILURE); + } + }; +} + +struct TmpFile { + string fname; + + TmpFile() { + char f[] = "/tmp/sqlite_modern_cpp_test_XXXXXX"; + int fid = mkstemp(f); + close(fid); + + fname = f; + } + + ~TmpFile() { + unlink(fname.c_str()); + } +}; + +int main() { + try { + // creates a database file 'dbfile.db' if it does not exists. + TmpFile file; + database db(file.fname); + + db << "drop table if exists test"; + db << + "create table if not exists test (" + " id integer primary key," + " val int" + ");"; + + insert(db, true); + select(db, true); + + insert(db, false); + select(db, false); + + } catch(exception& e) { + cout << e.what() << endl; + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} From 7e9dd24de3d3cdbfa22fb441bfe9f2c8ae12c9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Tue, 31 Jan 2017 07:41:04 +0100 Subject: [PATCH 3/3] Disable test if is missing. --- tests/std_optional.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/std_optional.cc b/tests/std_optional.cc index 64912db2..cb748ccf 100644 --- a/tests/std_optional.cc +++ b/tests/std_optional.cc @@ -6,6 +6,7 @@ using namespace sqlite; using namespace std; +#if __has_include() void insert(database& db, bool is_null) { int id = 1; std::optional val; @@ -66,3 +67,9 @@ int main() { } exit(EXIT_SUCCESS); } +#else +#pragma message " not found, test disabled." +int main() { + exit(EXIT_SUCCESS); +} +#endif