2929#endif
3030
3131#ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT
32- #include " sqlite_modern_cpp/utility/ variant.h "
32+ #include < variant>
3333#endif
3434
3535#include < sqlite3.h>
36+ #include " errors.h"
3637
3738namespace sqlite {
39+ template <class T , int Type, class = void >
40+ struct has_sqlite_type : std::false_type {};
41+
42+ template <class T , int Type>
43+ struct has_sqlite_type <T&, Type> : has_sqlite_type<T, Type> {};
44+ template <class T , int Type>
45+ struct has_sqlite_type <const T, Type> : has_sqlite_type<T, Type> {};
46+ template <class T , int Type>
47+ struct has_sqlite_type <volatile T, Type> : has_sqlite_type<T, Type> {};
48+
3849 // int
50+ template <>
51+ struct has_sqlite_type <int , SQLITE_INTEGER> : std::true_type {};
52+
3953 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const int & val) {
4054 return sqlite3_bind_int (stmt, inx, val);
4155 }
42- inline void store_result_in_db (sqlite3_context* db, const int & val) {
43- sqlite3_result_int (db, val);
56+ inline void store_result_in_db (sqlite3_context* db, const int & val) {
57+ sqlite3_result_int (db, val);
4458 }
45- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, int & val) {
59+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, int & val) {
4660 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
4761 val = 0 ;
4862 } else {
4963 val = sqlite3_column_int (stmt, inx);
5064 }
5165 }
52- inline void get_val_from_db (sqlite3_value *value, int & val) {
66+ inline void get_val_from_db (sqlite3_value *value, int & val) {
5367 if (sqlite3_value_type (value) == SQLITE_NULL) {
5468 val = 0 ;
5569 } else {
@@ -58,20 +72,23 @@ namespace sqlite {
5872 }
5973
6074 // sqlite_int64
75+ template <>
76+ struct has_sqlite_type <sqlite_int64, SQLITE_INTEGER, void > : std::true_type {};
77+
6178 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const sqlite_int64& val) {
6279 return sqlite3_bind_int64 (stmt, inx, val);
6380 }
64- inline void store_result_in_db (sqlite3_context* db, const sqlite_int64& val) {
65- sqlite3_result_int64 (db, val);
81+ inline void store_result_in_db (sqlite3_context* db, const sqlite_int64& val) {
82+ sqlite3_result_int64 (db, val);
6683 }
67- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, sqlite3_int64& i) {
84+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, sqlite3_int64& i) {
6885 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
6986 i = 0 ;
7087 } else {
7188 i = sqlite3_column_int64 (stmt, inx);
7289 }
7390 }
74- inline void get_val_from_db (sqlite3_value *value, sqlite3_int64& i) {
91+ inline void get_val_from_db (sqlite3_value *value, sqlite3_int64& i) {
7592 if (sqlite3_value_type (value) == SQLITE_NULL) {
7693 i = 0 ;
7794 } else {
@@ -80,20 +97,23 @@ namespace sqlite {
8097 }
8198
8299 // float
100+ template <>
101+ struct has_sqlite_type <float , SQLITE_FLOAT, void > : std::true_type {};
102+
83103 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const float & val) {
84104 return sqlite3_bind_double (stmt, inx, double (val));
85105 }
86- inline void store_result_in_db (sqlite3_context* db, const float & val) {
87- sqlite3_result_double (db, val);
106+ inline void store_result_in_db (sqlite3_context* db, const float & val) {
107+ sqlite3_result_double (db, val);
88108 }
89- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, float & f) {
109+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, float & f) {
90110 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
91111 f = 0 ;
92112 } else {
93113 f = float (sqlite3_column_double (stmt, inx));
94114 }
95115 }
96- inline void get_val_from_db (sqlite3_value *value, float & f) {
116+ inline void get_val_from_db (sqlite3_value *value, float & f) {
97117 if (sqlite3_value_type (value) == SQLITE_NULL) {
98118 f = 0 ;
99119 } else {
@@ -102,20 +122,23 @@ namespace sqlite {
102122 }
103123
104124 // double
125+ template <>
126+ struct has_sqlite_type <double , SQLITE_FLOAT, void > : std::true_type {};
127+
105128 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const double & val) {
106129 return sqlite3_bind_double (stmt, inx, val);
107130 }
108- inline void store_result_in_db (sqlite3_context* db, const double & val) {
109- sqlite3_result_double (db, val);
131+ inline void store_result_in_db (sqlite3_context* db, const double & val) {
132+ sqlite3_result_double (db, val);
110133 }
111- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, double & d) {
134+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, double & d) {
112135 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
113136 d = 0 ;
114137 } else {
115138 d = sqlite3_column_double (stmt, inx);
116139 }
117140 }
118- inline void get_val_from_db (sqlite3_value *value, double & d) {
141+ inline void get_val_from_db (sqlite3_value *value, double & d) {
119142 if (sqlite3_value_type (value) == SQLITE_NULL) {
120143 d = 0 ;
121144 } else {
@@ -124,30 +147,36 @@ namespace sqlite {
124147 }
125148
126149 /* for nullptr support */
150+ template <>
151+ struct has_sqlite_type <std::nullptr_t , SQLITE_NULL, void > : std::true_type {};
152+
127153 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, std::nullptr_t ) {
128154 return sqlite3_bind_null (stmt, inx);
129155 }
130- inline void store_result_in_db (sqlite3_context* db, std::nullptr_t ) {
131- sqlite3_result_null (db);
156+ inline void store_result_in_db (sqlite3_context* db, std::nullptr_t ) {
157+ sqlite3_result_null (db);
132158 }
133159
134160 // std::string
161+ template <>
162+ struct has_sqlite_type <std::string, SQLITE3_TEXT, void > : std::true_type {};
163+
135164 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const std::string& val) {
136165 return sqlite3_bind_text (stmt, inx, val.data (), -1 , SQLITE_TRANSIENT);
137166 }
138167
139168 // Convert char* to string to trigger op<<(..., const std::string )
140169 template <std::size_t N> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const char (&STR)[N]) { return bind_col_in_db (stmt, inx, std::string (STR, N-1 )); }
141170
142- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, std::string & s) {
171+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, std::string & s) {
143172 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
144173 s = std::string ();
145174 } else {
146175 sqlite3_column_bytes (stmt, inx);
147176 s = std::string (reinterpret_cast <char const *>(sqlite3_column_text (stmt, inx)));
148177 }
149178 }
150- inline void get_val_from_db (sqlite3_value *value, std::string & s) {
179+ inline void get_val_from_db (sqlite3_value *value, std::string & s) {
151180 if (sqlite3_value_type (value) == SQLITE_NULL) {
152181 s = std::string ();
153182 } else {
@@ -156,26 +185,29 @@ namespace sqlite {
156185 }
157186 }
158187
159- inline void store_result_in_db (sqlite3_context* db, const std::string& val) {
160- sqlite3_result_text (db, val.data (), -1 , SQLITE_TRANSIENT);
188+ inline void store_result_in_db (sqlite3_context* db, const std::string& val) {
189+ sqlite3_result_text (db, val.data (), -1 , SQLITE_TRANSIENT);
161190 }
162191 // std::u16string
192+ template <>
193+ struct has_sqlite_type <std::u16string, SQLITE3_TEXT, void > : std::true_type {};
194+
163195 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const std::u16string& val) {
164196 return sqlite3_bind_text16 (stmt, inx, val.data (), -1 , SQLITE_TRANSIENT);
165197 }
166198
167199 // Convert char* to string to trigger op<<(..., const std::string )
168200 template <std::size_t N> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const char16_t (&STR)[N]) { return bind_col_in_db (stmt, inx, std::u16string (STR, N-1 )); }
169201
170- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, std::u16string & w) {
202+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, std::u16string & w) {
171203 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
172204 w = std::u16string ();
173205 } else {
174206 sqlite3_column_bytes16 (stmt, inx);
175207 w = std::u16string (reinterpret_cast <char16_t const *>(sqlite3_column_text16 (stmt, inx)));
176208 }
177209 }
178- inline void get_val_from_db (sqlite3_value *value, std::u16string & w) {
210+ inline void get_val_from_db (sqlite3_value *value, std::u16string & w) {
179211 if (sqlite3_value_type (value) == SQLITE_NULL) {
180212 w = std::u16string ();
181213 } else {
@@ -184,33 +216,39 @@ namespace sqlite {
184216 }
185217 }
186218
187- inline void store_result_in_db (sqlite3_context* db, const std::u16string& val) {
188- sqlite3_result_text16 (db, val.data (), -1 , SQLITE_TRANSIENT);
219+ inline void store_result_in_db (sqlite3_context* db, const std::u16string& val) {
220+ sqlite3_result_text16 (db, val.data (), -1 , SQLITE_TRANSIENT);
189221 }
190222
191223 // Other integer types
224+ template <class Integral >
225+ struct has_sqlite_type <Integral, SQLITE_INTEGER, typename std::enable_if<std::is_integral<Integral>::value>::type> : std::true_type {};
226+
192227 template <class Integral , class = typename std::enable_if<std::is_integral<Integral>::value>::type>
193228 inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const Integral& val) {
194229 return bind_col_in_db (stmt, inx, static_cast <sqlite3_int64>(val));
195230 }
196- template <class Integral , class = std::enable_if<std::is_integral<Integral>::type>>
197- inline void store_result_in_db (sqlite3_context* db, const Integral& val) {
198- store_result_in_db (db, static_cast <sqlite3_int64>(val));
231+ template <class Integral , class = std::enable_if<std::is_integral<Integral>::type>>
232+ inline void store_result_in_db (sqlite3_context* db, const Integral& val) {
233+ store_result_in_db (db, static_cast <sqlite3_int64>(val));
199234 }
200- template <class Integral , class = typename std::enable_if<std::is_integral<Integral>::value>::type>
201- inline void get_col_from_db (sqlite3_stmt* stmt, int inx, Integral& val) {
235+ template <class Integral , class = typename std::enable_if<std::is_integral<Integral>::value>::type>
236+ inline void get_col_from_db (sqlite3_stmt* stmt, int inx, Integral& val) {
202237 sqlite3_int64 i;
203238 get_col_from_db (stmt, inx, i);
204239 val = i;
205240 }
206- template <class Integral , class = typename std::enable_if<std::is_integral<Integral>::value>::type>
207- inline void get_val_from_db (sqlite3_value *value, Integral& val) {
241+ template <class Integral , class = typename std::enable_if<std::is_integral<Integral>::value>::type>
242+ inline void get_val_from_db (sqlite3_value *value, Integral& val) {
208243 sqlite3_int64 i;
209244 get_val_from_db (value, i);
210245 val = i;
211246 }
212247
213248 // vector<T, A>
249+ template <typename T, typename A>
250+ struct has_sqlite_type <std::vector<T, A>, SQLITE_BLOB, void > : std::true_type {};
251+
214252 template <typename T, typename A> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const std::vector<T, A>& vec) {
215253 void const * buf = reinterpret_cast <void const *>(vec.data ());
216254 int bytes = vec.size () * sizeof (T);
@@ -241,6 +279,11 @@ namespace sqlite {
241279 }
242280
243281 /* for unique_ptr<T> support */
282+ template <typename T, int Type>
283+ struct has_sqlite_type <std::unique_ptr<T>, Type, void > : has_sqlite_type<T, Type> {};
284+ template <typename T>
285+ struct has_sqlite_type <std::unique_ptr<T>, SQLITE_NULL, void > : std::true_type {};
286+
244287 template <typename T> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const std::unique_ptr<T>& val) {
245288 return val ? bind_col_in_db (stmt, inx, *val) : bind_col_in_db (stmt, inx, nullptr );
246289 }
@@ -273,6 +316,11 @@ namespace sqlite {
273316 using optional = std::optional<T>;
274317#endif
275318
319+ template <typename T, int Type>
320+ struct has_sqlite_type <optional<T>, Type, void > : has_sqlite_type<T, Type> {};
321+ template <typename T>
322+ struct has_sqlite_type <optional<T>, SQLITE_NULL, void > : std::true_type {};
323+
276324 template <typename OptionalT> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const optional<OptionalT>& val) {
277325 return val ? bind_col_in_db (stmt, inx, *val) : bind_col_in_db (stmt, inx, nullptr );
278326 }
@@ -285,11 +333,11 @@ namespace sqlite {
285333
286334 template <typename OptionalT> inline void get_col_from_db (sqlite3_stmt* stmt, int inx, optional<OptionalT>& o) {
287335 if (sqlite3_column_type (stmt, inx) == SQLITE_NULL) {
288- #ifdef MODERN_SQLITE_EXPERIMENTAL_OPTIONAL_SUPPORT
336+ #ifdef MODERN_SQLITE_EXPERIMENTAL_OPTIONAL_SUPPORT
289337 o = std::experimental::nullopt ;
290- #else
338+ #else
291339 o.reset ();
292- #endif
340+ #endif
293341 } else {
294342 OptionalT v;
295343 get_col_from_db (stmt, inx, v);
@@ -298,11 +346,11 @@ namespace sqlite {
298346 }
299347 template <typename OptionalT> inline void get_val_from_db (sqlite3_value *value, optional<OptionalT>& o) {
300348 if (sqlite3_value_type (value) == SQLITE_NULL) {
301- #ifdef MODERN_SQLITE_EXPERIMENTAL_OPTIONAL_SUPPORT
349+ #ifdef MODERN_SQLITE_EXPERIMENTAL_OPTIONAL_SUPPORT
302350 o = std::experimental::nullopt ;
303- #else
351+ #else
304352 o.reset ();
305- #endif
353+ #endif
306354 } else {
307355 OptionalT v;
308356 get_val_from_db (value, v);
@@ -312,20 +360,57 @@ namespace sqlite {
312360#endif
313361
314362#ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT
363+ namespace detail {
364+ template <class T , class U >
365+ struct tag_trait : U { using tag = T; };
366+ }
367+
368+ template <int Type, class ...Options>
369+ struct has_sqlite_type <std::variant<Options...>, Type, void > : std::disjunction<detail::tag_trait<Options, has_sqlite_type<Options, Type>>...> {};
370+
371+ namespace detail {
372+ template <int Type, typename ...Options, typename Callback, typename first_compatible = has_sqlite_type<std::variant<Options...>, Type>>
373+ inline void variant_select_type (Callback &&callback) {
374+ if constexpr (first_compatible::value)
375+ callback (typename first_compatible::tag ());
376+ else
377+ throw errors::mismatch (" The value is unsupported by this variant." , " " , SQLITE_MISMATCH);
378+ }
379+ template <typename ...Options, typename Callback> inline void variant_select (int type, Callback &&callback) {
380+ switch (type) {
381+ case SQLITE_NULL:
382+ variant_select_type<SQLITE_NULL, Options...>(std::forward<Callback>(callback));
383+ break ;
384+ case SQLITE_INTEGER:
385+ variant_select_type<SQLITE_INTEGER, Options...>(std::forward<Callback>(callback));
386+ break ;
387+ case SQLITE_FLOAT:
388+ variant_select_type<SQLITE_FLOAT, Options...>(std::forward<Callback>(callback));
389+ break ;
390+ case SQLITE_TEXT:
391+ variant_select_type<SQLITE_TEXT, Options...>(std::forward<Callback>(callback));
392+ break ;
393+ case SQLITE_BLOB:
394+ variant_select_type<SQLITE_BLOB, Options...>(std::forward<Callback>(callback));
395+ break ;
396+ default :;
397+ }
398+ }
399+ }
315400 template <typename ...Args> inline int bind_col_in_db (sqlite3_stmt* stmt, int inx, const std::variant<Args...>& val) {
316401 return std::visit ([&](auto &&opt) {return bind_col_in_db (stmt, inx, std::forward<decltype (opt)>(opt));}, val);
317402 }
318403 template <typename ...Args> inline void store_result_in_db (sqlite3_context* db, const std::variant<Args...>& val) {
319404 std::visit ([&](auto &&opt) {store_result_in_db (db, std::forward<decltype (opt)>(opt));}, val);
320405 }
321406 template <typename ...Args> inline void get_col_from_db (sqlite3_stmt* stmt, int inx, std::variant<Args...>& val) {
322- utility ::variant_select<Args...>(sqlite3_column_type (stmt, inx))( [&](auto v) {
407+ detail ::variant_select<Args...>(sqlite3_column_type (stmt, inx), [&](auto v) {
323408 get_col_from_db (stmt, inx, v);
324409 val = std::move (v);
325410 });
326411 }
327412 template <typename ...Args> inline void get_val_from_db (sqlite3_value *value, std::variant<Args...>& val) {
328- utility ::variant_select<Args...>(sqlite3_value_type (value))( [&](auto v) {
413+ detail ::variant_select<Args...>(sqlite3_value_type (value), [&](auto v) {
329414 get_val_from_db (value, v);
330415 val = std::move (v);
331416 });
0 commit comments