@@ -76,16 +76,7 @@ namespace sqlite {
76
76
_stmt (std::move(other._stmt)),
77
77
_inx (other._inx), execution_started(other.execution_started) { }
78
78
79
- void execute () {
80
- _start_execute ();
81
- int hresult;
82
-
83
- while ((hresult = sqlite3_step (_stmt.get ())) == SQLITE_ROW) {}
84
-
85
- if (hresult != SQLITE_DONE) {
86
- errors::throw_sqlite_error (hresult, sql ());
87
- }
88
- }
79
+ void execute ();
89
80
90
81
std::string sql () {
91
82
#if SQLITE_VERSION_NUMBER >= 3014000
@@ -129,15 +120,6 @@ namespace sqlite {
129
120
}
130
121
return ++_inx;
131
122
}
132
- void _start_execute () {
133
- _next_index ();
134
- _inx = 0 ;
135
- used (true );
136
- }
137
-
138
- void _extract (std::function<void (void )> call_back);
139
-
140
- void _extract_single_value (std::function<void (void )> call_back);
141
123
142
124
#ifdef _MSC_VER
143
125
sqlite3_stmt* _prepare (const std::u16string& sql) {
@@ -160,31 +142,6 @@ namespace sqlite {
160
142
return tmp;
161
143
}
162
144
163
- template <typename Type>
164
- struct is_sqlite_value : public std ::integral_constant<
165
- bool ,
166
- std::is_floating_point<Type>::value
167
- || std::is_integral<Type>::value
168
- || std::is_same<std::string, Type>::value
169
- || std::is_same<std::u16string, Type>::value
170
- || std::is_same<sqlite_int64, Type>::value
171
- > { };
172
- template <typename Type, typename Allocator>
173
- struct is_sqlite_value < std::vector<Type, Allocator> > : public std::integral_constant<
174
- bool ,
175
- std::is_floating_point<Type>::value
176
- || std::is_integral<Type>::value
177
- || std::is_same<sqlite_int64, Type>::value
178
- > { };
179
- #ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT
180
- template <typename ...Args>
181
- struct is_sqlite_value < std::variant<Args...> > : public std::integral_constant<
182
- bool ,
183
- true
184
- > { };
185
- #endif
186
-
187
-
188
145
/* for vector<T, A> support */
189
146
template <typename T, typename A> friend database_binder& operator <<(database_binder& db, const std::vector<T, A>& val);
190
147
template <typename T, typename A> friend void get_col_from_db (database_binder& db, int inx, std::vector<T, A>& val);
@@ -244,43 +201,56 @@ namespace sqlite {
244
201
}
245
202
}
246
203
247
- template <typename Result>
248
- typename std::enable_if<is_sqlite_value<Result>::value, void >::type operator >>(
249
- Result& value) {
250
- this ->_extract_single_value ([&value, this ] {
251
- get_col_from_db (*this , 0 , value);
252
- });
253
- }
254
-
255
- template <typename ... Types>
256
- void operator >>(std::tuple<Types...>&& values) {
257
- this ->_extract_single_value ([&values, this ] {
258
- tuple_iterate<std::tuple<Types...>>::iterate(values, *this );
259
- });
260
- }
261
-
262
- template <typename Function>
263
- typename std::enable_if<!is_sqlite_value<Function>::value, void >::type operator >>(
264
- Function&& func) {
265
- typedef utility::function_traits<Function> traits;
266
-
267
- this ->_extract ([&func, this ]() {
268
- binder<traits::arity>::run (*this , func);
269
- });
270
- }
271
204
friend class row_iterator ;
272
205
};
206
+ namespace detail {
207
+ template <typename Type>
208
+ struct is_sqlite_value : public std ::integral_constant<
209
+ bool ,
210
+ std::is_floating_point<Type>::value
211
+ || std::is_integral<Type>::value
212
+ || std::is_same<std::string, Type>::value
213
+ || std::is_same<std::u16string, Type>::value
214
+ || std::is_same<sqlite_int64, Type>::value
215
+ > { };
216
+ template <typename Type, typename Allocator>
217
+ struct is_sqlite_value < std::vector<Type, Allocator> > : public std::integral_constant<
218
+ bool ,
219
+ std::is_floating_point<Type>::value
220
+ || std::is_integral<Type>::value
221
+ || std::is_same<sqlite_int64, Type>::value
222
+ > { };
223
+ template <typename T>
224
+ struct is_sqlite_value < std::unique_ptr<T> > : public is_sqlite_value<T> {};
225
+ #ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT
226
+ template <typename ...Args>
227
+ struct is_sqlite_value < std::variant<Args...> > : public std::integral_constant<
228
+ bool ,
229
+ true
230
+ > { };
231
+ #endif
232
+ #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
233
+ template <typename T>
234
+ struct is_sqlite_value < std::optional<T> > : public is_sqlite_value<T> {};
235
+ #endif
236
+
237
+ #ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT
238
+ template <typename T>
239
+ struct is_sqlite_value < boost::optional<T> > : public is_sqlite_value<T> {};
240
+ #endif
241
+ }
242
+
273
243
class row_iterator {
274
244
public:
275
245
class value_type {
276
246
public:
277
247
value_type (database_binder *_binder): _binder(_binder) {};
278
248
template <class T >
279
- typename std::enable_if<database_binder ::is_sqlite_value<T>::value, value_type &>::type operator >>(T &result) {
249
+ typename std::enable_if<detail ::is_sqlite_value<T>::value, value_type &>::type operator >>(T &result) {
280
250
get_col_from_db (*_binder, next_index++, result);
281
251
return *this ;
282
252
}
283
- template <class T , typename = typename std::enable_if<database_binder ::is_sqlite_value<T>::value, value_type &>::type>
253
+ template <class T , typename = typename std::enable_if<detail ::is_sqlite_value<T>::value, value_type &>::type>
284
254
operator T () {
285
255
T result;
286
256
*this >> result;
@@ -294,6 +264,10 @@ namespace sqlite {
294
264
return *this ;
295
265
}
296
266
template <class ...Types>
267
+ value_type &operator >>(std::tuple<Types...>&& values) {
268
+ return *this >> values;
269
+ }
270
+ template <class ...Types>
297
271
operator std::tuple<Types...>() {
298
272
std::tuple<Types...> value;
299
273
*this >> value;
@@ -313,7 +287,9 @@ namespace sqlite {
313
287
314
288
row_iterator () = default ;
315
289
explicit row_iterator (database_binder &binder): _binder(&binder) {
316
- _binder->_start_execute ();
290
+ _binder->_next_index ();
291
+ _binder->_inx = 0 ;
292
+ _binder->used (true );
317
293
++*this ;
318
294
}
319
295
@@ -323,7 +299,6 @@ namespace sqlite {
323
299
switch (int result = sqlite3_step (_binder->_stmt .get ())) {
324
300
case SQLITE_ROW:
325
301
value = {_binder};
326
- /* tuple_iterate<value_type>::iterate(_value, *_binder); */
327
302
break ;
328
303
case SQLITE_DONE:
329
304
_binder = nullptr ;
@@ -355,20 +330,53 @@ namespace sqlite {
355
330
inline row_iterator database_binder::end () {
356
331
return row_iterator ();
357
332
}
358
- void database_binder::_extract (std::function<void (void )> call_back) {
359
- for (auto &&row[[maybe_unused]] : *this )
360
- call_back ();
333
+
334
+ namespace detail {
335
+ template <class Callback >
336
+ void _extract_single_value (database_binder &binder, Callback call_back) {
337
+ auto iter = binder.begin ();
338
+ if (iter == binder.end ())
339
+ throw errors::no_rows (" no rows to extract: exactly 1 row expected" , binder.sql (), SQLITE_DONE);
340
+
341
+ call_back (*iter);
342
+
343
+ if (++iter != binder.end ())
344
+ throw errors::more_rows (" not all rows extracted" , binder.sql (), SQLITE_ROW);
345
+ }
346
+ }
347
+ void database_binder::execute () {
348
+ for (auto &&row : *this )
349
+ (void )row;
350
+ }
351
+ namespace detail {
352
+ template <class T > using void_t = void ;
353
+ template <class T , class = void >
354
+ struct sqlite_direct_result : std::false_type {};
355
+ template <class T >
356
+ struct sqlite_direct_result <
357
+ T,
358
+ void_t <decltype(std::declval<row_iterator::value_type&>().operator >>(std::declval<T&&>()))>
359
+ > : std::true_type {};
360
+ }
361
+ template <typename Result>
362
+ inline typename std::enable_if<detail::sqlite_direct_result<Result>::value>::type operator >>(database_binder &binder, Result&& value) {
363
+ detail::_extract_single_value (binder, [&value] (row_iterator::value_type &row) {
364
+ row >> std::forward<Result>(value);
365
+ });
361
366
}
362
367
363
- void database_binder::_extract_single_value (std::function<void (void )> call_back) {
364
- auto iter = begin ();
365
- if (iter == end ())
366
- throw errors::no_rows (" no rows to extract: exactly 1 row expected" , sql (), SQLITE_DONE);
368
+ template <typename Function>
369
+ inline typename std::enable_if<!detail::sqlite_direct_result<Function>::value>::type operator >>(database_binder &db_binder, Function&& func) {
370
+ using traits = utility::function_traits<Function>;
367
371
368
- call_back ();
372
+ for (auto &&row : db_binder) {
373
+ binder<traits::arity>::run (row, func);
374
+ }
375
+ }
369
376
370
- if (++iter != end ())
371
- throw errors::more_rows (" not all rows extracted" , sql (), SQLITE_ROW);
377
+ template <typename Result>
378
+ inline decltype (auto ) operator>>(database_binder &&binder, Result&& value) {
379
+ return binder >> std::forward<Result>(value);
372
380
}
373
381
374
382
namespace sql_function_binder {
@@ -573,14 +581,13 @@ namespace sqlite {
573
581
std::size_t Boundary = Count
574
582
>
575
583
static typename std::enable_if<(sizeof ...(Values) < Boundary), void >::type run (
576
- database_binder& db ,
577
- Function&& function,
578
- Values&&... values
584
+ row_iterator::value_type& row ,
585
+ Function&& function,
586
+ Values&&... values
579
587
) {
580
- typename std::remove_cv<typename std::remove_reference<nth_argument_type<Function, sizeof ...(Values)>>::type>::type value{};
581
- get_col_from_db (db, sizeof ...(Values), value);
582
-
583
- run<Function>(db, function, std::forward<Values>(values)..., std::move (value));
588
+ typename std::decay<nth_argument_type<Function, sizeof ...(Values)>>::type value;
589
+ row >> value;
590
+ run<Function>(row, function, std::forward<Values>(values)..., std::move (value));
584
591
}
585
592
586
593
template <
@@ -589,9 +596,9 @@ namespace sqlite {
589
596
std::size_t Boundary = Count
590
597
>
591
598
static typename std::enable_if<(sizeof ...(Values) == Boundary), void >::type run (
592
- database_binder &,
593
- Function&& function,
594
- Values&&... values
599
+ row_iterator::value_type &,
600
+ Function&& function,
601
+ Values&&... values
595
602
) {
596
603
function (std::move (values)...);
597
604
}
0 commit comments