Skip to content

Commit cf01458

Browse files
authored
Merge pull request #75 from zauguin/std_optional
std::optional support
2 parents 0974493 + 7e9dd24 commit cf01458

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

hdr/sqlite_modern_cpp.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include <memory>
99
#include <vector>
1010

11+
#if __has_include(<optional>)
12+
#include <optional>
13+
#endif
14+
1115
#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
1216
#include <boost/optional.hpp>
1317
#endif
@@ -237,6 +241,11 @@ namespace sqlite {
237241
friend database_binder& operator <<(database_binder& db, const std::u16string& txt);
238242

239243

244+
#if __has_include(<optional>)
245+
template <typename OptionalT> friend database_binder& operator <<(database_binder& db, const std::optional<OptionalT>& val);
246+
template <typename OptionalT> friend void get_col_from_db(database_binder& db, int inx, std::optional<OptionalT>& o);
247+
#endif
248+
240249
#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
241250
template <typename BoostOptionalT> friend database_binder& operator <<(database_binder& db, const boost::optional<BoostOptionalT>& val);
242251
template <typename BoostOptionalT> friend void get_col_from_db(database_binder& db, int inx, boost::optional<BoostOptionalT>& o);
@@ -545,7 +554,33 @@ namespace sqlite {
545554
++db._inx;
546555
return db;
547556
}
548-
// boost::optinal support for NULL values
557+
// std::optional support for NULL values
558+
#if __has_include(<optional>)
559+
template <typename OptionalT> inline database_binder& operator <<(database_binder& db, const std::optional<OptionalT>& val) {
560+
if(val) {
561+
return operator << (std::move(db), std::move(*val));
562+
}
563+
int hresult;
564+
if((hresult = sqlite3_bind_null(db._stmt.get(), db._inx)) != SQLITE_OK) {
565+
exceptions::throw_sqlite_error(hresult);
566+
}
567+
568+
++db._inx;
569+
return db;
570+
}
571+
572+
template <typename OptionalT> inline void get_col_from_db(database_binder& db, int inx, std::optional<OptionalT>& o) {
573+
if(sqlite3_column_type(db._stmt.get(), inx) == SQLITE_NULL) {
574+
o.reset();
575+
} else {
576+
OptionalT v;
577+
get_col_from_db(db, inx, v);
578+
o = std::move(v);
579+
}
580+
}
581+
#endif
582+
583+
// boost::optional support for NULL values
549584
#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
550585
template <typename BoostOptionalT> inline database_binder& operator <<(database_binder& db, const boost::optional<BoostOptionalT>& val) {
551586
if(val) {
@@ -574,7 +609,7 @@ namespace sqlite {
574609
// Some ppl are lazy so we have a operator for proper prep. statemant handling.
575610
void inline operator++(database_binder& db, int) { db.execute(); db.reset(); }
576611

577-
// 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!)
612+
// 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!)
578613
template<typename T> database_binder& operator << (database_binder&& db, const T& val) { return db << val; }
579614

580615
}

tests/std_optional.cc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <unistd.h>
2+
#include <iostream>
3+
4+
#include <sqlite_modern_cpp.h>
5+
6+
using namespace sqlite;
7+
using namespace std;
8+
9+
#if __has_include(<optional>)
10+
void insert(database& db, bool is_null) {
11+
int id = 1;
12+
std::optional<int> val;
13+
if(!is_null) val = 5;
14+
15+
db << "delete from test where id = 1";
16+
db << "insert into test(id,val) values(?,?)" << id << val;
17+
}
18+
19+
void select(database& db, bool should_be_null) {
20+
db << "select id,val from test" >> [&](long long, std::optional<int> val) {
21+
if(should_be_null) {
22+
if(val) exit(EXIT_FAILURE);
23+
} else {
24+
if(!val) exit(EXIT_FAILURE);
25+
}
26+
};
27+
}
28+
29+
struct TmpFile {
30+
string fname;
31+
32+
TmpFile() {
33+
char f[] = "/tmp/sqlite_modern_cpp_test_XXXXXX";
34+
int fid = mkstemp(f);
35+
close(fid);
36+
37+
fname = f;
38+
}
39+
40+
~TmpFile() {
41+
unlink(fname.c_str());
42+
}
43+
};
44+
45+
int main() {
46+
try {
47+
// creates a database file 'dbfile.db' if it does not exists.
48+
TmpFile file;
49+
database db(file.fname);
50+
51+
db << "drop table if exists test";
52+
db <<
53+
"create table if not exists test ("
54+
" id integer primary key,"
55+
" val int"
56+
");";
57+
58+
insert(db, true);
59+
select(db, true);
60+
61+
insert(db, false);
62+
select(db, false);
63+
64+
} catch(exception& e) {
65+
cout << e.what() << endl;
66+
exit(EXIT_FAILURE);
67+
}
68+
exit(EXIT_SUCCESS);
69+
}
70+
#else
71+
#pragma message "<optional> not found, test disabled."
72+
int main() {
73+
exit(EXIT_SUCCESS);
74+
}
75+
#endif

0 commit comments

Comments
 (0)