@@ -62,6 +62,7 @@ namespace sqlite {
6262 static void iterate(Tuple&, database_binder&) {}
6363 };
6464
65+ class row_iterator ;
6566 class database_binder {
6667
6768 public:
@@ -109,6 +110,8 @@ namespace sqlite {
109110 execution_started = state;
110111 }
111112 bool used () const { return execution_started; }
113+ row_iterator begin ();
114+ row_iterator end ();
112115
113116 private:
114117 std::shared_ptr<sqlite3> _db;
@@ -293,7 +296,88 @@ namespace sqlite {
293296 binder<traits::arity>::run (*this , func);
294297 });
295298 }
299+ friend class row_iterator ;
296300 };
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+ }
297381
298382 namespace sql_function_binder {
299383 template <
@@ -886,7 +970,7 @@ namespace sqlite {
886970 void inline operator ++(database_binder& db, int ) { db.execute (); }
887971
888972 // 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); }
890974
891975 namespace sql_function_binder {
892976 template <class T >
0 commit comments