@@ -81,6 +81,7 @@ namespace sqlite {
8181 static void iterate(Tuple&, database_binder&) {}
8282 };
8383
84+ class row_iterator ;
8485 class database_binder {
8586
8687 public:
@@ -128,6 +129,8 @@ namespace sqlite {
128129 execution_started = state;
129130 }
130131 bool used () const { return execution_started; }
132+ row_iterator begin ();
133+ row_iterator end ();
131134
132135 private:
133136 std::shared_ptr<sqlite3> _db;
@@ -312,7 +315,88 @@ namespace sqlite {
312315 binder<traits::arity>::run (*this , func);
313316 });
314317 }
318+ friend class row_iterator ;
315319 };
320+ class row_iterator {
321+ public:
322+ class value_type {
323+ public:
324+ value_type (database_binder *_binder): _binder(_binder) {};
325+ template <class T >
326+ value_type &operator >>(T &result) {
327+ get_col_from_db (*_binder, next_index++, result);
328+ return *this ;
329+ }
330+ template <class ...Types>
331+ value_type &operator >>(std::tuple<Types...>& values) {
332+ assert (!next_index);
333+ tuple_iterate<std::tuple<Types...>>::iterate(values, *_binder);
334+ next_index = sizeof ...(Types) + 1 ;
335+ return *this ;
336+ }
337+ explicit operator bool () {
338+ return sqlite3_column_count (_binder->_stmt .get ()) >= next_index;
339+ }
340+ template <class Type >
341+ operator Type () {
342+ Type value;
343+ *this >> value;
344+ return value;
345+ }
346+ private:
347+ database_binder *_binder;
348+ int next_index = 0 ;
349+ };
350+ using difference_type = std::ptrdiff_t ;
351+ using pointer = value_type*;
352+ using reference = value_type&;
353+ using iterator_category = std::input_iterator_tag;
354+
355+ row_iterator () = default ;
356+ explicit row_iterator (database_binder &binder): _binder(&binder) {
357+ _binder->_start_execute ();
358+ ++*this ;
359+ }
360+
361+ reference operator *() const { return value;}
362+ pointer operator ->() const { return std::addressof (**this ); }
363+ row_iterator &operator ++() {
364+ switch (int result = sqlite3_step (_binder->_stmt .get ())) {
365+ case SQLITE_ROW:
366+ value = {_binder};
367+ /* tuple_iterate<value_type>::iterate(_value, *_binder); */
368+ break ;
369+ case SQLITE_DONE:
370+ _binder = nullptr ;
371+ break ;
372+ default :
373+ _binder = nullptr ;
374+ exceptions::throw_sqlite_error (result, _binder->sql ());
375+ }
376+ return *this ;
377+ }
378+
379+ // Not well-defined
380+ row_iterator operator ++(int );
381+ friend inline bool operator ==(const row_iterator &a, const row_iterator &b) {
382+ return a._binder == b._binder ;
383+ }
384+ friend inline bool operator !=(const row_iterator &a, const row_iterator &b) {
385+ return !(a==b);
386+ }
387+
388+ private:
389+ database_binder *_binder = nullptr ;
390+ mutable value_type value{_binder}; // mutable, because `changing` the value is just reading it
391+ };
392+
393+ inline row_iterator database_binder::begin () {
394+ return row_iterator (*this );
395+ }
396+
397+ inline row_iterator database_binder::end () {
398+ return row_iterator ();
399+ }
316400
317401 namespace sql_function_binder {
318402 template <
@@ -913,7 +997,7 @@ namespace sqlite {
913997 void inline operator ++(database_binder& db, int ) { db.execute (); }
914998
915999 // 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!)
916- template <typename T> database_binder&& operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
1000+ template <typename T> database_binder operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
9171001
9181002 namespace sql_function_binder {
9191003 template <class T >
0 commit comments