@@ -62,6 +62,7 @@ namespace sqlite {
62
62
static void iterate(Tuple&, database_binder&) {}
63
63
};
64
64
65
+ class row_iterator ;
65
66
class database_binder {
66
67
67
68
public:
@@ -109,6 +110,8 @@ namespace sqlite {
109
110
execution_started = state;
110
111
}
111
112
bool used () const { return execution_started; }
113
+ row_iterator begin ();
114
+ row_iterator end ();
112
115
113
116
private:
114
117
std::shared_ptr<sqlite3> _db;
@@ -293,7 +296,88 @@ namespace sqlite {
293
296
binder<traits::arity>::run (*this , func);
294
297
});
295
298
}
299
+ friend class row_iterator ;
296
300
};
301
+ class row_iterator {
302
+ public:
303
+ class value_type {
304
+ public:
305
+ value_type (database_binder *_binder): _binder(_binder) {};
306
+ template <class T >
307
+ value_type &operator >>(T &result) {
308
+ get_col_from_db (*_binder, next_index++, result);
309
+ return *this ;
310
+ }
311
+ template <class ...Types>
312
+ value_type &operator >>(std::tuple<Types...>& values) {
313
+ assert (!next_index);
314
+ tuple_iterate<std::tuple<Types...>>::iterate(values, *_binder);
315
+ next_index = sizeof ...(Types) + 1 ;
316
+ return *this ;
317
+ }
318
+ explicit operator bool () {
319
+ return sqlite3_column_count (_binder->_stmt .get ()) >= next_index;
320
+ }
321
+ template <class Type >
322
+ operator Type () {
323
+ Type value;
324
+ *this >> value;
325
+ return value;
326
+ }
327
+ private:
328
+ database_binder *_binder;
329
+ int next_index = 0 ;
330
+ };
331
+ using difference_type = std::ptrdiff_t ;
332
+ using pointer = value_type*;
333
+ using reference = value_type&;
334
+ using iterator_category = std::input_iterator_tag;
335
+
336
+ row_iterator () = default ;
337
+ explicit row_iterator (database_binder &binder): _binder(&binder) {
338
+ _binder->_start_execute ();
339
+ ++*this ;
340
+ }
341
+
342
+ reference operator *() const { return value;}
343
+ pointer operator ->() const { return std::addressof (**this ); }
344
+ row_iterator &operator ++() {
345
+ switch (int result = sqlite3_step (_binder->_stmt .get ())) {
346
+ case SQLITE_ROW:
347
+ value = {_binder};
348
+ /* tuple_iterate<value_type>::iterate(_value, *_binder); */
349
+ break ;
350
+ case SQLITE_DONE:
351
+ _binder = nullptr ;
352
+ break ;
353
+ default :
354
+ _binder = nullptr ;
355
+ exceptions::throw_sqlite_error (result, _binder->sql ());
356
+ }
357
+ return *this ;
358
+ }
359
+
360
+ // Not well-defined
361
+ row_iterator operator ++(int );
362
+ friend inline bool operator ==(const row_iterator &a, const row_iterator &b) {
363
+ return a._binder == b._binder ;
364
+ }
365
+ friend inline bool operator !=(const row_iterator &a, const row_iterator &b) {
366
+ return !(a==b);
367
+ }
368
+
369
+ private:
370
+ database_binder *_binder = nullptr ;
371
+ mutable value_type value{_binder}; // mutable, because `changing` the value is just reading it
372
+ };
373
+
374
+ inline row_iterator database_binder::begin () {
375
+ return row_iterator (*this );
376
+ }
377
+
378
+ inline row_iterator database_binder::end () {
379
+ return row_iterator ();
380
+ }
297
381
298
382
namespace sql_function_binder {
299
383
template <
@@ -886,7 +970,7 @@ namespace sqlite {
886
970
void inline operator ++(database_binder& db, int ) { db.execute (); }
887
971
888
972
// 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!)
889
- template <typename T> database_binder&& operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
973
+ template <typename T> database_binder operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
890
974
891
975
namespace sql_function_binder {
892
976
template <class T >
0 commit comments