Commit 3971b4b5 by Konstantin Käfer

save

parent 69a9eafa
var sqlite3 = require('./lib/sqlite3');
var db = new sqlite3.Database(':memory:');
db.prepare("CREATE TABLE foo (text bar)")
.run(function(err) {
console.log('x');
})
.finalize()
.close();
...@@ -34,6 +34,7 @@ void Statement::Init(v8::Handle<Object> target) { ...@@ -34,6 +34,7 @@ void Statement::Init(v8::Handle<Object> target) {
constructor_template->InstanceTemplate()->SetInternalFieldCount(1); constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Statement")); constructor_template->SetClassName(String::NewSymbol("Statement"));
NODE_SET_PROTOTYPE_METHOD(constructor_template, "run", Run);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize); NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize);
target->Set(v8::String::NewSymbol("Statement"), target->Set(v8::String::NewSymbol("Statement"),
...@@ -67,6 +68,19 @@ void Statement::Schedule(EIO_Callback callback, Baton* baton) { ...@@ -67,6 +68,19 @@ void Statement::Schedule(EIO_Callback callback, Baton* baton) {
} }
} }
template <class T> void Statement::Error(T* baton) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { exception };
TRY_CATCH_CALL(baton->stmt->handle_, baton->callback, 1, argv);
}
else {
Local<Value> argv[] = { String::NewSymbol("error"), exception };
EMIT_EVENT(baton->stmt->handle_, 2, argv);
}
}
// { Database db, String sql, Array params, Function callback } // { Database db, String sql, Array params, Function callback }
Handle<Value> Statement::New(const Arguments& args) { Handle<Value> Statement::New(const Arguments& args) {
HandleScope scope; HandleScope scope;
...@@ -163,42 +177,108 @@ int Statement::EIO_AfterPrepare(eio_req *req) { ...@@ -163,42 +177,108 @@ int Statement::EIO_AfterPrepare(eio_req *req) {
Database* db = baton->db; Database* db = baton->db;
Statement* stmt = baton->stmt; Statement* stmt = baton->stmt;
Local<Value> argv[1];
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); Error(baton);
argv[0] = exception; stmt->Finalize();
} }
else { else {
stmt->prepared = true; stmt->prepared = true;
argv[0] = Local<Value>::New(Null()); if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
}
stmt->Process();
} }
fprintf(stderr, "after prepare\n"); db->Process();
// Fire callbacks. delete baton;
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { return 0;
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); }
Handle<Value> Statement::Run(const Arguments& args) {
HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback);
Baton* baton = new Baton(stmt, callback);
stmt->Schedule(EIO_BeginRun, baton);
return args.This();
}
void Statement::EIO_BeginRun(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Run, EIO_PRI_DEFAULT, EIO_AfterRun, baton);
}
int Statement::EIO_Run(eio_req *req) {
Baton* baton = static_cast<Baton*>(req->data);
Statement* stmt = baton->stmt;
Database* db = stmt->db;
fprintf(stderr, "calling run\n");
// In case preparing fails, we use a mutex to make sure we get the associated
// error message.
sqlite3_mutex* mtx = sqlite3_db_mutex(db->handle);
sqlite3_mutex_enter(mtx);
baton->status = sqlite3_step(stmt->handle);
if (!(baton->status == SQLITE_ROW || baton->status == SQLITE_DONE)) {
baton->message = std::string(sqlite3_errmsg(db->handle));
} }
else if (!stmt->prepared) {
Local<Value> args[] = { String::NewSymbol("error"), argv[0] }; sqlite3_mutex_leave(mtx);
EMIT_EVENT(stmt->handle_, 2, args);
if (baton->status == SQLITE_ROW) {
Locker lock;
HandleScope scope;
Local<Value> argv[] = { Local<Value>::New(Null()) };
for (int i = 0; i < 10; i++) {
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
TryCatch try_catch;
baton->callback->Call(baton->stmt->handle_, 1, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
}
}
} }
db->Process(); return 0;
}
if (stmt->prepared) { int Statement::EIO_AfterRun(eio_req *req) {
stmt->Process(); HandleScope scope;
Baton* baton = static_cast<Baton*>(req->data);
Statement* stmt = baton->stmt;
if (baton->status != SQLITE_ROW && baton->status != SQLITE_DONE) {
Error(baton);
} }
else { else {
stmt->Finalize(); // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
}
} }
stmt->locked = false;
stmt->Process();
delete baton; delete baton;
return 0; return 0;
} }
Handle<Value> Statement::Finalize(const Arguments& args) { Handle<Value> Statement::Finalize(const Arguments& args) {
HandleScope scope; HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
......
...@@ -89,18 +89,22 @@ public: ...@@ -89,18 +89,22 @@ public:
} }
protected: protected:
static Handle<Value> Run(const Arguments& args);
static void EIO_BeginRun(Baton* baton);
static int EIO_Run(eio_req *req);
static int EIO_AfterRun(eio_req *req);
static void EIO_BeginPrepare(Database::Baton* baton); static void EIO_BeginPrepare(Database::Baton* baton);
static int EIO_Prepare(eio_req *req); static int EIO_Prepare(eio_req *req);
static int EIO_AfterPrepare(eio_req *req); static int EIO_AfterPrepare(eio_req *req);
void Schedule(EIO_Callback callback, Baton* baton); void Schedule(EIO_Callback callback, Baton* baton);
void Process(); void Process();
void CleanQueue(); void CleanQueue();
static Handle<Value> Finalize(const Arguments& args); static Handle<Value> Finalize(const Arguments& args);
static void Finalize(Baton* baton); static void Finalize(Baton* baton);
template <class T> static void Error(T* baton);
void Finalize(); void Finalize();
protected: protected:
Database* db; Database* db;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment