@@ -27,6 +27,7 @@ void Statement::Init(Handle<Object> target) {
2727 NODE_SET_PROTOTYPE_METHOD (constructor_template, " get" , Get);
2828 NODE_SET_PROTOTYPE_METHOD (constructor_template, " run" , Run);
2929 NODE_SET_PROTOTYPE_METHOD (constructor_template, " all" , All);
30+ NODE_SET_PROTOTYPE_METHOD (constructor_template, " each" , Each);
3031 NODE_SET_PROTOTYPE_METHOD (constructor_template, " reset" , Reset);
3132 NODE_SET_PROTOTYPE_METHOD (constructor_template, " finalize" , Finalize);
3233
@@ -101,14 +102,14 @@ Handle<Value> Statement::New(const Arguments& args) {
101102
102103 Statement* stmt = new Statement (db);
103104 stmt->Wrap (args.This ());
105+
104106 PrepareBaton* baton = new PrepareBaton (db, Local<Function>::Cast (args[2 ]), stmt);
105107 baton->sql = std::string (*String::Utf8Value (sql));
106108 db->Schedule (EIO_BeginPrepare, baton);
107109
108110 return args.This ();
109111}
110112
111-
112113void Statement::EIO_BeginPrepare (Database::Baton* baton) {
113114 assert (baton->db ->open );
114115 baton->db ->pending ++;
@@ -520,6 +521,117 @@ int Statement::EIO_AfterAll(eio_req *req) {
520521 return 0 ;
521522}
522523
524+ Handle<Value> Statement::Each (const Arguments& args) {
525+ HandleScope scope;
526+ Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This ());
527+
528+ Baton* baton = stmt->Bind <Baton>(args);
529+ if (baton == NULL ) {
530+ return ThrowException (Exception::Error (String::New (" Data type is not supported" )));
531+ }
532+ else {
533+ stmt->Schedule (EIO_BeginEach, baton);
534+ return args.This ();
535+ }
536+ }
537+
538+ void Statement::EIO_BeginEach (Baton* baton) {
539+ STATEMENT_BEGIN (Each);
540+ }
541+
542+ int Statement::EIO_Each (eio_req *req) {
543+ STATEMENT_INIT (Baton);
544+
545+ Async* async = new Async (stmt, baton->callback , AsyncEach);
546+
547+ sqlite3_mutex* mtx = sqlite3_db_mutex (stmt->db ->handle );
548+
549+ int retrieved = 0 ;
550+
551+ // Make sure that we also reset when there are no parameters.
552+ if (!baton->parameters .size ()) {
553+ sqlite3_reset (stmt->handle );
554+ }
555+
556+ if (stmt->Bind (baton->parameters )) {
557+ while (true ) {
558+ sqlite3_mutex_enter (mtx);
559+ stmt->status = sqlite3_step (stmt->handle );
560+ if (stmt->status == SQLITE_ROW) {
561+ sqlite3_mutex_leave (mtx);
562+ Data::Row* row = new Data::Row ();
563+ GetRow (row, stmt->handle );
564+
565+ pthread_mutex_lock (&async->mutex );
566+ async->data .push_back (row);
567+ retrieved++;
568+ pthread_mutex_unlock (&async->mutex );
569+
570+ ev_async_send (EV_DEFAULT_ &async->watcher );
571+ }
572+ else {
573+ if (stmt->status != SQLITE_DONE) {
574+ stmt->message = std::string (sqlite3_errmsg (stmt->db ->handle ));
575+ }
576+ sqlite3_mutex_leave (mtx);
577+ break ;
578+ }
579+ }
580+ }
581+
582+ async->completed = true ;
583+ ev_async_send (EV_DEFAULT_ &async->watcher );
584+
585+ return 0 ;
586+ }
587+
588+ void Statement::AsyncEach (EV_P_ ev_async *w, int revents) {
589+ HandleScope scope;
590+ Async* async = static_cast <Async*>(w->data );
591+
592+ while (true ) {
593+ // Get the contents out of the data cache for us to process in the JS callback.
594+ Data::Rows rows;
595+ pthread_mutex_lock (&async->mutex );
596+ rows.swap (async->data );
597+ pthread_mutex_unlock (&async->mutex );
598+
599+ if (rows.empty ()) {
600+ break ;
601+ }
602+
603+ if (!async->callback .IsEmpty () && async->callback ->IsFunction ()) {
604+ Local<Value> argv[2 ];
605+ argv[0 ] = Local<Value>::New (Null ());
606+
607+ Data::Rows::const_iterator it = rows.begin ();
608+ Data::Rows::const_iterator end = rows.end ();
609+ for (int i = 0 ; it < end; it++, i++) {
610+ argv[1 ] = RowToJS (*it);
611+ TRY_CATCH_CALL (async->stmt ->handle_ , async->callback , 2 , argv);
612+ delete *it;
613+ }
614+ }
615+ }
616+
617+ if (async->completed ) {
618+ delete async;
619+ w->data = NULL ;
620+ }
621+ }
622+
623+ int Statement::EIO_AfterEach (eio_req *req) {
624+ HandleScope scope;
625+ STATEMENT_INIT (Baton);
626+
627+ if (stmt->status != SQLITE_DONE) {
628+ Error (baton);
629+ }
630+
631+ STATEMENT_END ();
632+ return 0 ;
633+ }
634+
523635Handle<Value> Statement::Reset (const Arguments& args) {
524636 HandleScope scope;
525637 Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This ());
0 commit comments