Commit 6c2295dc by Dane Springmeyer

Merge remote-tracking branch 'kkoopa/master'

Conflicts:
	package.json
parents 6ec345d9 4267d542
...@@ -4,6 +4,7 @@ env: ...@@ -4,6 +4,7 @@ env:
matrix: matrix:
- export NODE_VERSION="0.8" - export NODE_VERSION="0.8"
- export NODE_VERSION="0.10" NODE_WEBKIT="0.8.6" - export NODE_VERSION="0.10" NODE_WEBKIT="0.8.6"
- export NODE_VERSION="0.11"
global: global:
- secure: QhuP5E/kYL1j1KDkHGJtk6DSJr1RH4DR/JrC62Viuf5Du8jE+i0kPWfF2MxtuEmKo35orhpu8t8mzKygWfuO63WPuuIE9qd/+V/y99Lqcj0tEN6wJ5RnywktbTJWg23zphjhmYq3Xj8DLVEikCZBwHtlbygkO9Q60cn1PK+bnPg= - secure: QhuP5E/kYL1j1KDkHGJtk6DSJr1RH4DR/JrC62Viuf5Du8jE+i0kPWfF2MxtuEmKo35orhpu8t8mzKygWfuO63WPuuIE9qd/+V/y99Lqcj0tEN6wJ5RnywktbTJWg23zphjhmYq3Xj8DLVEikCZBwHtlbygkO9Q60cn1PK+bnPg=
- secure: HxCS2dQAWI0KmCFnFNNZoucG4FeAW+itG7+Hp0dNtwmxZzGOZYFO2bZcGvTAMNfVN++oqLxTebYQI1oB5yUl5mPJjrjthaGS6Zq3S6rfJcXiv+icYgEXlR6ejQ97dsHw1Jeg8nedCQlI4kHfvG6pgBLhq9hnugxH1Cjhdt14E9U= - secure: HxCS2dQAWI0KmCFnFNNZoucG4FeAW+itG7+Hp0dNtwmxZzGOZYFO2bZcGvTAMNfVN++oqLxTebYQI1oB5yUl5mPJjrjthaGS6Zq3S6rfJcXiv+icYgEXlR6ejQ97dsHw1Jeg8nedCQlI4kHfvG6pgBLhq9hnugxH1Cjhdt14E9U=
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"targets": [ "targets": [
{ {
"target_name": "<(module_name)", "target_name": "<(module_name)",
"include_dirs": ["<!(node -e \"require('nan')\")"],
"conditions": [ "conditions": [
["sqlite != 'internal'", { ["sqlite != 'internal'", {
"libraries": [ "libraries": [
......
...@@ -36,7 +36,10 @@ ...@@ -36,7 +36,10 @@
"url": "git://github.com/mapbox/node-sqlite3.git" "url": "git://github.com/mapbox/node-sqlite3.git"
}, },
"dependencies": { "dependencies": {
"node-pre-gyp": "0.5.13" "node-pre-gyp": "0.5.13",
"nan": "1.1.2",
"node-pre-gyp": "0.5.13",
"set-immediate": "0.1.1"
}, },
"bundledDependencies": [ "bundledDependencies": [
"node-pre-gyp" "node-pre-gyp"
...@@ -45,7 +48,7 @@ ...@@ -45,7 +48,7 @@
"mocha": "*" "mocha": "*"
}, },
"engines": { "engines": {
"node": ">= 0.8.0 < 0.11.0" "node": ">= 0.8.0 < 0.13.0"
}, },
"scripts": { "scripts": {
"install": "node-pre-gyp install --fallback-to-build", "install": "node-pre-gyp install --fallback-to-build",
......
...@@ -26,7 +26,7 @@ public: ...@@ -26,7 +26,7 @@ public:
: callback(cb_), parent(parent_) { : callback(cb_), parent(parent_) {
watcher.data = this; watcher.data = this;
NODE_SQLITE3_MUTEX_INIT NODE_SQLITE3_MUTEX_INIT
uv_async_init(uv_default_loop(), &watcher, listener); uv_async_init(uv_default_loop(), &watcher, reinterpret_cast<uv_async_cb>(listener));
} }
static void listener(uv_async_t* handle, int status) { static void listener(uv_async_t* handle, int status) {
......
...@@ -10,39 +10,43 @@ using namespace node_sqlite3; ...@@ -10,39 +10,43 @@ using namespace node_sqlite3;
Persistent<FunctionTemplate> Database::constructor_template; Persistent<FunctionTemplate> Database::constructor_template;
void Database::Init(Handle<Object> target) { void Database::Init(Handle<Object> target) {
HandleScope scope; NanScope();
Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
constructor_template = Persistent<FunctionTemplate>::New(t); t->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(NanNew("Database"));
constructor_template->SetClassName(String::NewSymbol("Database"));
NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close); NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec); NODE_SET_PROTOTYPE_METHOD(t, "exec", Exec);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "wait", Wait); NODE_SET_PROTOTYPE_METHOD(t, "wait", Wait);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadExtension", LoadExtension); NODE_SET_PROTOTYPE_METHOD(t, "loadExtension", LoadExtension);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize); NODE_SET_PROTOTYPE_METHOD(t, "serialize", Serialize);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize); NODE_SET_PROTOTYPE_METHOD(t, "parallelize", Parallelize);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure); NODE_SET_PROTOTYPE_METHOD(t, "configure", Configure);
NODE_SET_GETTER(constructor_template, "open", OpenGetter); NODE_SET_GETTER(t, "open", OpenGetter);
target->Set(String::NewSymbol("Database"), NanAssignPersistent(constructor_template, t);
constructor_template->GetFunction());
target->Set(NanNew("Database"),
t->GetFunction());
} }
void Database::Process() { void Database::Process() {
NanScope();
if (!open && locked && !queue.empty()) { if (!open && locked && !queue.empty()) {
EXCEPTION(String::New("Database handle is closed"), SQLITE_MISUSE, exception); EXCEPTION(NanNew<String>("Database handle is closed"), SQLITE_MISUSE, exception);
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
bool called = false; bool called = false;
// Call all callbacks with the error object. // Call all callbacks with the error object.
while (!queue.empty()) { while (!queue.empty()) {
Call* call = queue.front(); Call* call = queue.front();
if (!call->baton->callback.IsEmpty() && call->baton->callback->IsFunction()) { Local<Function> cb = NanNew(call->baton->callback);
TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv); if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv);
called = true; called = true;
} }
queue.pop(); queue.pop();
...@@ -55,8 +59,8 @@ void Database::Process() { ...@@ -55,8 +59,8 @@ void Database::Process() {
// When we couldn't call a callback function, emit an error on the // When we couldn't call a callback function, emit an error on the
// Database object. // Database object.
if (!called) { if (!called) {
Local<Value> args[] = { String::NewSymbol("error"), exception }; Local<Value> args[] = { NanNew("error"), exception };
EMIT_EVENT(handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(this), 2, args);
} }
return; return;
} }
...@@ -78,15 +82,17 @@ void Database::Process() { ...@@ -78,15 +82,17 @@ void Database::Process() {
} }
void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) {
NanScope();
if (!open && locked) { if (!open && locked) {
EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception); EXCEPTION(NanNew<String>("Database is closed"), SQLITE_MISUSE, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
TRY_CATCH_CALL(handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv);
} }
else { else {
Local<Value> argv[] = { String::NewSymbol("error"), exception }; Local<Value> argv[] = { NanNew("error"), exception };
EMIT_EVENT(handle_, 2, argv); EMIT_EVENT(NanObjectWrapHandle(this), 2, argv);
} }
return; return;
} }
...@@ -100,13 +106,11 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { ...@@ -100,13 +106,11 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) {
} }
} }
Handle<Value> Database::New(const Arguments& args) { NAN_METHOD(Database::New) {
HandleScope scope; NanScope();
if (!args.IsConstructCall()) { if (!args.IsConstructCall()) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("Use the new operator to create new Database objects");
String::New("Use the new operator to create new Database objects"))
);
} }
REQUIRE_ARGUMENT_STRING(0, filename); REQUIRE_ARGUMENT_STRING(0, filename);
...@@ -127,14 +131,14 @@ Handle<Value> Database::New(const Arguments& args) { ...@@ -127,14 +131,14 @@ Handle<Value> Database::New(const Arguments& args) {
Database* db = new Database(); Database* db = new Database();
db->Wrap(args.This()); db->Wrap(args.This());
args.This()->Set(String::NewSymbol("filename"), args[0]->ToString(), ReadOnly); args.This()->Set(NanNew("filename"), args[0]->ToString(), ReadOnly);
args.This()->Set(String::NewSymbol("mode"), Integer::New(mode), ReadOnly); args.This()->Set(NanNew("mode"), NanNew<Integer>(mode), ReadOnly);
// Start opening the database. // Start opening the database.
OpenBaton* baton = new OpenBaton(db, callback, *filename, mode); OpenBaton* baton = new OpenBaton(db, callback, *filename, mode);
Work_BeginOpen(baton); Work_BeginOpen(baton);
return args.This(); NanReturnValue(args.This());
} }
void Database::Work_BeginOpen(Baton* baton) { void Database::Work_BeginOpen(Baton* baton) {
...@@ -149,75 +153,77 @@ void Database::Work_Open(uv_work_t* req) { ...@@ -149,75 +153,77 @@ void Database::Work_Open(uv_work_t* req) {
baton->status = sqlite3_open_v2( baton->status = sqlite3_open_v2(
baton->filename.c_str(), baton->filename.c_str(),
&db->handle, &db->_handle,
baton->mode, baton->mode,
NULL NULL
); );
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
baton->message = std::string(sqlite3_errmsg(db->handle)); baton->message = std::string(sqlite3_errmsg(db->_handle));
sqlite3_close(db->handle); sqlite3_close(db->_handle);
db->handle = NULL; db->_handle = NULL;
} }
else { else {
// Set default database handle values. // Set default database handle values.
sqlite3_busy_timeout(db->handle, 1000); sqlite3_busy_timeout(db->_handle, 1000);
} }
} }
void Database::Work_AfterOpen(uv_work_t* req) { void Database::Work_AfterOpen(uv_work_t* req) {
HandleScope scope; NanScope();
OpenBaton* baton = static_cast<OpenBaton*>(req->data); OpenBaton* baton = static_cast<OpenBaton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
Local<Value> argv[1]; Local<Value> argv[1];
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); EXCEPTION(NanNew<String>(baton->message.c_str()), baton->status, exception);
argv[0] = exception; argv[0] = exception;
} }
else { else {
db->open = true; db->open = true;
argv[0] = Local<Value>::New(Null()); argv[0] = NanNew(NanNull());
} }
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
else if (!db->open) { else if (!db->open) {
Local<Value> args[] = { String::NewSymbol("error"), argv[0] }; Local<Value> args[] = { NanNew("error"), argv[0] };
EMIT_EVENT(db->handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(db), 2, args);
} }
if (db->open) { if (db->open) {
Local<Value> args[] = { String::NewSymbol("open") }; Local<Value> args[] = { NanNew("open") };
EMIT_EVENT(db->handle_, 1, args); EMIT_EVENT(NanObjectWrapHandle(db), 1, args);
db->Process(); db->Process();
} }
delete baton; delete baton;
} }
Handle<Value> Database::OpenGetter(Local<String> str, const AccessorInfo& accessor) { NAN_GETTER(Database::OpenGetter) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(accessor.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
return Boolean::New(db->open); NanReturnValue(NanNew<Boolean>(db->open));
} }
Handle<Value> Database::Close(const Arguments& args) { NAN_METHOD(Database::Close) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
Baton* baton = new Baton(db, callback); Baton* baton = new Baton(db, callback);
db->Schedule(Work_BeginClose, baton, true); db->Schedule(Work_BeginClose, baton, true);
return args.This(); NanReturnValue(args.This());
} }
void Database::Work_BeginClose(Baton* baton) { void Database::Work_BeginClose(Baton* baton) {
assert(baton->db->locked); assert(baton->db->locked);
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
assert(baton->db->pending == 0); assert(baton->db->pending == 0);
baton->db->RemoveCallbacks(); baton->db->RemoveCallbacks();
...@@ -230,53 +236,55 @@ void Database::Work_Close(uv_work_t* req) { ...@@ -230,53 +236,55 @@ void Database::Work_Close(uv_work_t* req) {
Baton* baton = static_cast<Baton*>(req->data); Baton* baton = static_cast<Baton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
baton->status = sqlite3_close(db->handle); baton->status = sqlite3_close(db->_handle);
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
baton->message = std::string(sqlite3_errmsg(db->handle)); baton->message = std::string(sqlite3_errmsg(db->_handle));
} }
else { else {
db->handle = NULL; db->_handle = NULL;
} }
} }
void Database::Work_AfterClose(uv_work_t* req) { void Database::Work_AfterClose(uv_work_t* req) {
HandleScope scope; NanScope();
Baton* baton = static_cast<Baton*>(req->data); Baton* baton = static_cast<Baton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
Local<Value> argv[1]; Local<Value> argv[1];
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); EXCEPTION(NanNew<String>(baton->message.c_str()), baton->status, exception);
argv[0] = exception; argv[0] = exception;
} }
else { else {
db->open = false; db->open = false;
// Leave db->locked to indicate that this db object has reached // Leave db->locked to indicate that this db object has reached
// the end of its life. // the end of its life.
argv[0] = Local<Value>::New(Null()); argv[0] = NanNew(NanNull());
} }
Local<Function> cb = NanNew(baton->callback);
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
else if (db->open) { else if (db->open) {
Local<Value> args[] = { String::NewSymbol("error"), argv[0] }; Local<Value> args[] = { NanNew("error"), argv[0] };
EMIT_EVENT(db->handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(db), 2, args);
} }
if (!db->open) { if (!db->open) {
Local<Value> args[] = { String::NewSymbol("close"), argv[0] }; Local<Value> args[] = { NanNew("close"), argv[0] };
EMIT_EVENT(db->handle_, 1, args); EMIT_EVENT(NanObjectWrapHandle(db), 1, args);
db->Process(); db->Process();
} }
delete baton; delete baton;
} }
Handle<Value> Database::Serialize(const Arguments& args) { NAN_METHOD(Database::Serialize) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
...@@ -290,11 +298,11 @@ Handle<Value> Database::Serialize(const Arguments& args) { ...@@ -290,11 +298,11 @@ Handle<Value> Database::Serialize(const Arguments& args) {
db->Process(); db->Process();
return args.This(); NanReturnValue(args.This());
} }
Handle<Value> Database::Parallelize(const Arguments& args) { NAN_METHOD(Database::Parallelize) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
...@@ -308,30 +316,28 @@ Handle<Value> Database::Parallelize(const Arguments& args) { ...@@ -308,30 +316,28 @@ Handle<Value> Database::Parallelize(const Arguments& args) {
db->Process(); db->Process();
return args.This(); NanReturnValue(args.This());
} }
Handle<Value> Database::Configure(const Arguments& args) { NAN_METHOD(Database::Configure) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
REQUIRE_ARGUMENTS(2); REQUIRE_ARGUMENTS(2);
if (args[0]->Equals(String::NewSymbol("trace"))) { if (args[0]->Equals(NanNew("trace"))) {
Local<Function> handle; Local<Function> handle;
Baton* baton = new Baton(db, handle); Baton* baton = new Baton(db, handle);
db->Schedule(RegisterTraceCallback, baton); db->Schedule(RegisterTraceCallback, baton);
} }
else if (args[0]->Equals(String::NewSymbol("profile"))) { else if (args[0]->Equals(NanNew("profile"))) {
Local<Function> handle; Local<Function> handle;
Baton* baton = new Baton(db, handle); Baton* baton = new Baton(db, handle);
db->Schedule(RegisterProfileCallback, baton); db->Schedule(RegisterProfileCallback, baton);
} }
else if (args[0]->Equals(String::NewSymbol("busyTimeout"))) { else if (args[0]->Equals(NanNew("busyTimeout"))) {
if (!args[1]->IsInt32()) { if (!args[1]->IsInt32()) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("Value must be an integer");
String::New("Value must be an integer"))
);
} }
Local<Function> handle; Local<Function> handle;
Baton* baton = new Baton(db, handle); Baton* baton = new Baton(db, handle);
...@@ -339,40 +345,40 @@ Handle<Value> Database::Configure(const Arguments& args) { ...@@ -339,40 +345,40 @@ Handle<Value> Database::Configure(const Arguments& args) {
db->Schedule(SetBusyTimeout, baton); db->Schedule(SetBusyTimeout, baton);
} }
else { else {
return ThrowException(Exception::Error(String::Concat( return NanThrowError(Exception::Error(String::Concat(
args[0]->ToString(), args[0]->ToString(),
String::NewSymbol(" is not a valid configuration option") NanNew<String>(" is not a valid configuration option")
))); )));
} }
db->Process(); db->Process();
return args.This(); NanReturnValue(args.This());
} }
void Database::SetBusyTimeout(Baton* baton) { void Database::SetBusyTimeout(Baton* baton) {
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
// Abuse the status field for passing the timeout. // Abuse the status field for passing the timeout.
sqlite3_busy_timeout(baton->db->handle, baton->status); sqlite3_busy_timeout(baton->db->_handle, baton->status);
delete baton; delete baton;
} }
void Database::RegisterTraceCallback(Baton* baton) { void Database::RegisterTraceCallback(Baton* baton) {
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
Database* db = baton->db; Database* db = baton->db;
if (db->debug_trace == NULL) { if (db->debug_trace == NULL) {
// Add it. // Add it.
db->debug_trace = new AsyncTrace(db, TraceCallback); db->debug_trace = new AsyncTrace(db, TraceCallback);
sqlite3_trace(db->handle, TraceCallback, db); sqlite3_trace(db->_handle, TraceCallback, db);
} }
else { else {
// Remove it. // Remove it.
sqlite3_trace(db->handle, NULL, NULL); sqlite3_trace(db->_handle, NULL, NULL);
db->debug_trace->finish(); db->debug_trace->finish();
db->debug_trace = NULL; db->debug_trace = NULL;
} }
...@@ -388,28 +394,28 @@ void Database::TraceCallback(void* db, const char* sql) { ...@@ -388,28 +394,28 @@ void Database::TraceCallback(void* db, const char* sql) {
void Database::TraceCallback(Database* db, std::string* sql) { void Database::TraceCallback(Database* db, std::string* sql) {
// Note: This function is called in the main V8 thread. // Note: This function is called in the main V8 thread.
HandleScope scope; NanScope();
Local<Value> argv[] = { Local<Value> argv[] = {
String::NewSymbol("trace"), NanNew("trace"),
String::New(sql->c_str()) NanNew<String>(sql->c_str())
}; };
EMIT_EVENT(db->handle_, 2, argv); EMIT_EVENT(NanObjectWrapHandle(db), 2, argv);
delete sql; delete sql;
} }
void Database::RegisterProfileCallback(Baton* baton) { void Database::RegisterProfileCallback(Baton* baton) {
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
Database* db = baton->db; Database* db = baton->db;
if (db->debug_profile == NULL) { if (db->debug_profile == NULL) {
// Add it. // Add it.
db->debug_profile = new AsyncProfile(db, ProfileCallback); db->debug_profile = new AsyncProfile(db, ProfileCallback);
sqlite3_profile(db->handle, ProfileCallback, db); sqlite3_profile(db->_handle, ProfileCallback, db);
} }
else { else {
// Remove it. // Remove it.
sqlite3_profile(db->handle, NULL, NULL); sqlite3_profile(db->_handle, NULL, NULL);
db->debug_profile->finish(); db->debug_profile->finish();
db->debug_profile = NULL; db->debug_profile = NULL;
} }
...@@ -427,29 +433,29 @@ void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) ...@@ -427,29 +433,29 @@ void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs)
} }
void Database::ProfileCallback(Database *db, ProfileInfo* info) { void Database::ProfileCallback(Database *db, ProfileInfo* info) {
HandleScope scope; NanScope();
Local<Value> argv[] = { Local<Value> argv[] = {
String::NewSymbol("profile"), NanNew("profile"),
String::New(info->sql.c_str()), NanNew<String>(info->sql.c_str()),
Integer::New((double)info->nsecs / 1000000.0) NanNew<Integer>((double)info->nsecs / 1000000.0)
}; };
EMIT_EVENT(db->handle_, 3, argv); EMIT_EVENT(NanObjectWrapHandle(db), 3, argv);
delete info; delete info;
} }
void Database::RegisterUpdateCallback(Baton* baton) { void Database::RegisterUpdateCallback(Baton* baton) {
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
Database* db = baton->db; Database* db = baton->db;
if (db->update_event == NULL) { if (db->update_event == NULL) {
// Add it. // Add it.
db->update_event = new AsyncUpdate(db, UpdateCallback); db->update_event = new AsyncUpdate(db, UpdateCallback);
sqlite3_update_hook(db->handle, UpdateCallback, db); sqlite3_update_hook(db->_handle, UpdateCallback, db);
} }
else { else {
// Remove it. // Remove it.
sqlite3_update_hook(db->handle, NULL, NULL); sqlite3_update_hook(db->_handle, NULL, NULL);
db->update_event->finish(); db->update_event->finish();
db->update_event = NULL; db->update_event = NULL;
} }
...@@ -470,20 +476,20 @@ void Database::UpdateCallback(void* db, int type, const char* database, ...@@ -470,20 +476,20 @@ void Database::UpdateCallback(void* db, int type, const char* database,
} }
void Database::UpdateCallback(Database *db, UpdateInfo* info) { void Database::UpdateCallback(Database *db, UpdateInfo* info) {
HandleScope scope; NanScope();
Local<Value> argv[] = { Local<Value> argv[] = {
String::NewSymbol(sqlite_authorizer_string(info->type)), NanNew(sqlite_authorizer_string(info->type)),
String::New(info->database.c_str()), NanNew<String>(info->database.c_str()),
String::New(info->table.c_str()), NanNew<String>(info->table.c_str()),
Integer::New(info->rowid), NanNew<Integer>(info->rowid),
}; };
EMIT_EVENT(db->handle_, 4, argv); EMIT_EVENT(NanObjectWrapHandle(db), 4, argv);
delete info; delete info;
} }
Handle<Value> Database::Exec(const Arguments& args) { NAN_METHOD(Database::Exec) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
REQUIRE_ARGUMENT_STRING(0, sql); REQUIRE_ARGUMENT_STRING(0, sql);
...@@ -492,13 +498,13 @@ Handle<Value> Database::Exec(const Arguments& args) { ...@@ -492,13 +498,13 @@ Handle<Value> Database::Exec(const Arguments& args) {
Baton* baton = new ExecBaton(db, callback, *sql); Baton* baton = new ExecBaton(db, callback, *sql);
db->Schedule(Work_BeginExec, baton, true); db->Schedule(Work_BeginExec, baton, true);
return args.This(); NanReturnValue(args.This());
} }
void Database::Work_BeginExec(Baton* baton) { void Database::Work_BeginExec(Baton* baton) {
assert(baton->db->locked); assert(baton->db->locked);
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
assert(baton->db->pending == 0); assert(baton->db->pending == 0);
int status = uv_queue_work(uv_default_loop(), int status = uv_queue_work(uv_default_loop(),
&baton->request, Work_Exec, (uv_after_work_cb)Work_AfterExec); &baton->request, Work_Exec, (uv_after_work_cb)Work_AfterExec);
...@@ -510,7 +516,7 @@ void Database::Work_Exec(uv_work_t* req) { ...@@ -510,7 +516,7 @@ void Database::Work_Exec(uv_work_t* req) {
char* message = NULL; char* message = NULL;
baton->status = sqlite3_exec( baton->status = sqlite3_exec(
baton->db->handle, baton->db->_handle,
baton->sql.c_str(), baton->sql.c_str(),
NULL, NULL,
NULL, NULL,
...@@ -524,26 +530,27 @@ void Database::Work_Exec(uv_work_t* req) { ...@@ -524,26 +530,27 @@ void Database::Work_Exec(uv_work_t* req) {
} }
void Database::Work_AfterExec(uv_work_t* req) { void Database::Work_AfterExec(uv_work_t* req) {
HandleScope scope; NanScope();
ExecBaton* baton = static_cast<ExecBaton*>(req->data); ExecBaton* baton = static_cast<ExecBaton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
Local<Function> cb = NanNew(baton->callback);
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); EXCEPTION(NanNew<String>(baton->message.c_str()), baton->status, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
else { else {
Local<Value> args[] = { String::NewSymbol("error"), exception }; Local<Value> args[] = { NanNew("error"), exception };
EMIT_EVENT(db->handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(db), 2, args);
} }
} }
else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { else if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) }; Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
db->Process(); db->Process();
...@@ -551,8 +558,8 @@ void Database::Work_AfterExec(uv_work_t* req) { ...@@ -551,8 +558,8 @@ void Database::Work_AfterExec(uv_work_t* req) {
delete baton; delete baton;
} }
Handle<Value> Database::Wait(const Arguments& args) { NAN_METHOD(Database::Wait) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
...@@ -560,20 +567,21 @@ Handle<Value> Database::Wait(const Arguments& args) { ...@@ -560,20 +567,21 @@ Handle<Value> Database::Wait(const Arguments& args) {
Baton* baton = new Baton(db, callback); Baton* baton = new Baton(db, callback);
db->Schedule(Work_Wait, baton, true); db->Schedule(Work_Wait, baton, true);
return args.This(); NanReturnValue(args.This());
} }
void Database::Work_Wait(Baton* baton) { void Database::Work_Wait(Baton* baton) {
HandleScope scope; NanScope();
assert(baton->db->locked); assert(baton->db->locked);
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
assert(baton->db->pending == 0); assert(baton->db->pending == 0);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
Local<Value> argv[] = { Local<Value>::New(Null()) }; if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(baton->db->handle_, baton->callback, 1, argv); Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(NanObjectWrapHandle(baton->db), cb, 1, argv);
} }
baton->db->Process(); baton->db->Process();
...@@ -581,8 +589,8 @@ void Database::Work_Wait(Baton* baton) { ...@@ -581,8 +589,8 @@ void Database::Work_Wait(Baton* baton) {
delete baton; delete baton;
} }
Handle<Value> Database::LoadExtension(const Arguments& args) { NAN_METHOD(Database::LoadExtension) {
HandleScope scope; NanScope();
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
REQUIRE_ARGUMENT_STRING(0, filename); REQUIRE_ARGUMENT_STRING(0, filename);
...@@ -591,13 +599,13 @@ Handle<Value> Database::LoadExtension(const Arguments& args) { ...@@ -591,13 +599,13 @@ Handle<Value> Database::LoadExtension(const Arguments& args) {
Baton* baton = new LoadExtensionBaton(db, callback, *filename); Baton* baton = new LoadExtensionBaton(db, callback, *filename);
db->Schedule(Work_BeginLoadExtension, baton, true); db->Schedule(Work_BeginLoadExtension, baton, true);
return args.This(); NanReturnValue(args.This());
} }
void Database::Work_BeginLoadExtension(Baton* baton) { void Database::Work_BeginLoadExtension(Baton* baton) {
assert(baton->db->locked); assert(baton->db->locked);
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->_handle);
assert(baton->db->pending == 0); assert(baton->db->pending == 0);
int status = uv_queue_work(uv_default_loop(), int status = uv_queue_work(uv_default_loop(),
&baton->request, Work_LoadExtension, (uv_after_work_cb)Work_AfterLoadExtension); &baton->request, Work_LoadExtension, (uv_after_work_cb)Work_AfterLoadExtension);
...@@ -607,17 +615,17 @@ void Database::Work_BeginLoadExtension(Baton* baton) { ...@@ -607,17 +615,17 @@ void Database::Work_BeginLoadExtension(Baton* baton) {
void Database::Work_LoadExtension(uv_work_t* req) { void Database::Work_LoadExtension(uv_work_t* req) {
LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data); LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
sqlite3_enable_load_extension(baton->db->handle, 1); sqlite3_enable_load_extension(baton->db->_handle, 1);
char* message = NULL; char* message = NULL;
baton->status = sqlite3_load_extension( baton->status = sqlite3_load_extension(
baton->db->handle, baton->db->_handle,
baton->filename.c_str(), baton->filename.c_str(),
0, 0,
&message &message
); );
sqlite3_enable_load_extension(baton->db->handle, 0); sqlite3_enable_load_extension(baton->db->_handle, 0);
if (baton->status != SQLITE_OK && message != NULL) { if (baton->status != SQLITE_OK && message != NULL) {
baton->message = std::string(message); baton->message = std::string(message);
...@@ -626,25 +634,26 @@ void Database::Work_LoadExtension(uv_work_t* req) { ...@@ -626,25 +634,26 @@ void Database::Work_LoadExtension(uv_work_t* req) {
} }
void Database::Work_AfterLoadExtension(uv_work_t* req) { void Database::Work_AfterLoadExtension(uv_work_t* req) {
HandleScope scope; NanScope();
LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data); LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
Local<Function> cb = NanNew(baton->callback);
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); EXCEPTION(NanNew<String>(baton->message.c_str()), baton->status, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
else { else {
Local<Value> args[] = { String::NewSymbol("error"), exception }; Local<Value> args[] = { NanNew("error"), exception };
EMIT_EVENT(db->handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(db), 2, args);
} }
} }
else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { else if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) }; Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv);
} }
db->Process(); db->Process();
......
#ifndef NODE_SQLITE3_SRC_DATABASE_H #ifndef NODE_SQLITE3_SRC_DATABASE_H
#define NODE_SQLITE3_SRC_DATABASE_H #define NODE_SQLITE3_SRC_DATABASE_H
...@@ -7,6 +8,7 @@ ...@@ -7,6 +8,7 @@
#include <queue> #include <queue>
#include <sqlite3.h> #include <sqlite3.h>
#include "nan.h"
#include "async.h" #include "async.h"
using namespace v8; using namespace v8;
...@@ -23,9 +25,10 @@ public: ...@@ -23,9 +25,10 @@ public:
static void Init(Handle<Object> target); static void Init(Handle<Object> target);
static inline bool HasInstance(Handle<Value> val) { static inline bool HasInstance(Handle<Value> val) {
NanScope();
if (!val->IsObject()) return false; if (!val->IsObject()) return false;
Local<Object> obj = val->ToObject(); Local<Object> obj = val->ToObject();
return constructor_template->HasInstance(obj); return NanNew(constructor_template)->HasInstance(obj);
} }
struct Baton { struct Baton {
...@@ -39,11 +42,11 @@ public: ...@@ -39,11 +42,11 @@ public:
db(db_), status(SQLITE_OK) { db(db_), status(SQLITE_OK) {
db->Ref(); db->Ref();
request.data = this; request.data = this;
callback = Persistent<Function>::New(cb_); NanAssignPersistent(callback, cb_);
} }
virtual ~Baton() { virtual ~Baton() {
db->Unref(); db->Unref();
callback.Dispose(); NanDisposePersistent(callback);
} }
}; };
...@@ -99,7 +102,7 @@ public: ...@@ -99,7 +102,7 @@ public:
protected: protected:
Database() : ObjectWrap(), Database() : ObjectWrap(),
handle(NULL), _handle(NULL),
open(false), open(false),
locked(false), locked(false),
pending(0), pending(0),
...@@ -107,48 +110,47 @@ protected: ...@@ -107,48 +110,47 @@ protected:
debug_trace(NULL), debug_trace(NULL),
debug_profile(NULL), debug_profile(NULL),
update_event(NULL) { update_event(NULL) {
} }
~Database() { ~Database() {
RemoveCallbacks(); RemoveCallbacks();
sqlite3_close(handle); sqlite3_close(_handle);
handle = NULL; _handle = NULL;
open = false; open = false;
} }
static Handle<Value> New(const Arguments& args); static NAN_METHOD(New);
static void Work_BeginOpen(Baton* baton); static void Work_BeginOpen(Baton* baton);
static void Work_Open(uv_work_t* req); static void Work_Open(uv_work_t* req);
static void Work_AfterOpen(uv_work_t* req); static void Work_AfterOpen(uv_work_t* req);
static Handle<Value> OpenGetter(Local<String> str, const AccessorInfo& accessor); static NAN_GETTER(OpenGetter);
void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false); void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false);
void Process(); void Process();
static Handle<Value> Exec(const Arguments& args); static NAN_METHOD(Exec);
static void Work_BeginExec(Baton* baton); static void Work_BeginExec(Baton* baton);
static void Work_Exec(uv_work_t* req); static void Work_Exec(uv_work_t* req);
static void Work_AfterExec(uv_work_t* req); static void Work_AfterExec(uv_work_t* req);
static Handle<Value> Wait(const Arguments& args); static NAN_METHOD(Wait);
static void Work_Wait(Baton* baton); static void Work_Wait(Baton* baton);
static Handle<Value> Close(const Arguments& args); static NAN_METHOD(Close);
static void Work_BeginClose(Baton* baton); static void Work_BeginClose(Baton* baton);
static void Work_Close(uv_work_t* req); static void Work_Close(uv_work_t* req);
static void Work_AfterClose(uv_work_t* req); static void Work_AfterClose(uv_work_t* req);
static Handle<Value> LoadExtension(const Arguments& args); static NAN_METHOD(LoadExtension);
static void Work_BeginLoadExtension(Baton* baton); static void Work_BeginLoadExtension(Baton* baton);
static void Work_LoadExtension(uv_work_t* req); static void Work_LoadExtension(uv_work_t* req);
static void Work_AfterLoadExtension(uv_work_t* req); static void Work_AfterLoadExtension(uv_work_t* req);
static Handle<Value> Serialize(const Arguments& args); static NAN_METHOD(Serialize);
static Handle<Value> Parallelize(const Arguments& args); static NAN_METHOD(Parallelize);
static Handle<Value> Configure(const Arguments& args); static NAN_METHOD(Configure);
static void SetBusyTimeout(Baton* baton); static void SetBusyTimeout(Baton* baton);
...@@ -167,7 +169,7 @@ protected: ...@@ -167,7 +169,7 @@ protected:
void RemoveCallbacks(); void RemoveCallbacks();
protected: protected:
sqlite3* handle; sqlite3* _handle;
bool open; bool open;
bool locked; bool locked;
......
...@@ -7,35 +7,27 @@ const char* sqlite_authorizer_string(int type); ...@@ -7,35 +7,27 @@ const char* sqlite_authorizer_string(int type);
#define REQUIRE_ARGUMENTS(n) \ #define REQUIRE_ARGUMENTS(n) \
if (args.Length() < (n)) { \ if (args.Length() < (n)) { \
return ThrowException( \ return NanThrowTypeError("Expected " #n "arguments"); \
Exception::TypeError(String::New("Expected " #n "arguments")) \
); \
} }
#define REQUIRE_ARGUMENT_EXTERNAL(i, var) \ #define REQUIRE_ARGUMENT_EXTERNAL(i, var) \
if (args.Length() <= (i) || !args[i]->IsExternal()) { \ if (args.Length() <= (i) || !args[i]->IsExternal()) { \
return ThrowException( \ return NanThrowTypeError("Argument " #i " invalid"); \
Exception::TypeError(String::New("Argument " #i " invalid")) \
); \
} \ } \
Local<External> var = Local<External>::Cast(args[i]); Local<External> var = Local<External>::Cast(args[i]);
#define REQUIRE_ARGUMENT_FUNCTION(i, var) \ #define REQUIRE_ARGUMENT_FUNCTION(i, var) \
if (args.Length() <= (i) || !args[i]->IsFunction()) { \ if (args.Length() <= (i) || !args[i]->IsFunction()) { \
return ThrowException(Exception::TypeError( \ return NanThrowTypeError("Argument " #i " must be a function"); \
String::New("Argument " #i " must be a function")) \
); \
} \ } \
Local<Function> var = Local<Function>::Cast(args[i]); Local<Function> var = Local<Function>::Cast(args[i]);
#define REQUIRE_ARGUMENT_STRING(i, var) \ #define REQUIRE_ARGUMENT_STRING(i, var) \
if (args.Length() <= (i) || !args[i]->IsString()) { \ if (args.Length() <= (i) || !args[i]->IsString()) { \
return ThrowException(Exception::TypeError( \ return NanThrowTypeError("Argument " #i " must be a string"); \
String::New("Argument " #i " must be a string")) \
); \
} \ } \
String::Utf8Value var(args[i]->ToString()); String::Utf8Value var(args[i]->ToString());
...@@ -44,9 +36,7 @@ const char* sqlite_authorizer_string(int type); ...@@ -44,9 +36,7 @@ const char* sqlite_authorizer_string(int type);
Local<Function> var; \ Local<Function> var; \
if (args.Length() > i && !args[i]->IsUndefined()) { \ if (args.Length() > i && !args[i]->IsUndefined()) { \
if (!args[i]->IsFunction()) { \ if (!args[i]->IsFunction()) { \
return ThrowException(Exception::TypeError( \ return NanThrowTypeError("Argument " #i " must be a function"); \
String::New("Argument " #i " must be a function")) \
); \
} \ } \
var = Local<Function>::Cast(args[i]); \ var = Local<Function>::Cast(args[i]); \
} }
...@@ -61,68 +51,62 @@ const char* sqlite_authorizer_string(int type); ...@@ -61,68 +51,62 @@ const char* sqlite_authorizer_string(int type);
var = args[i]->Int32Value(); \ var = args[i]->Int32Value(); \
} \ } \
else { \ else { \
return ThrowException(Exception::TypeError( \ return NanThrowTypeError("Argument " #i " must be an integer"); \
String::New("Argument " #i " must be an integer")) \
); \
} }
#define DEFINE_CONSTANT_INTEGER(target, constant, name) \ #define DEFINE_CONSTANT_INTEGER(target, constant, name) \
(target)->Set( \ (target)->Set( \
String::NewSymbol(#name), \ NanNew(#name), \
Integer::New(constant), \ NanNew<Integer>(constant), \
static_cast<PropertyAttribute>(ReadOnly | DontDelete) \ static_cast<PropertyAttribute>(ReadOnly | DontDelete) \
); );
#define DEFINE_CONSTANT_STRING(target, constant, name) \ #define DEFINE_CONSTANT_STRING(target, constant, name) \
(target)->Set( \ (target)->Set( \
String::NewSymbol(#name), \ NanNew(#name), \
String::NewSymbol(constant), \ NanNew(constant), \
static_cast<PropertyAttribute>(ReadOnly | DontDelete) \ static_cast<PropertyAttribute>(ReadOnly | DontDelete) \
); );
#define NODE_SET_GETTER(target, name, function) \ #define NODE_SET_GETTER(target, name, function) \
(target)->InstanceTemplate() \ (target)->InstanceTemplate() \
->SetAccessor(String::NewSymbol(name), (function)); ->SetAccessor(NanNew(name), (function));
#define GET_STRING(source, name, property) \ #define GET_STRING(source, name, property) \
String::Utf8Value name((source)->Get(String::NewSymbol(property))); String::Utf8Value name((source)->Get(NanNew(property)));
#define GET_INTEGER(source, name, property) \ #define GET_INTEGER(source, name, property) \
int name = (source)->Get(String::NewSymbol(property))->Int32Value(); int name = (source)->Get(NanNew(property))->Int32Value();
#define EXCEPTION(msg, errno, name) \ #define EXCEPTION(msg, errno, name) \
Local<Value> name = Exception::Error( \ Local<Value> name = Exception::Error( \
String::Concat( \ String::Concat( \
String::Concat( \ String::Concat( \
String::NewSymbol(sqlite_code_string(errno)), \ NanNew(sqlite_code_string(errno)), \
String::NewSymbol(": ") \ NanNew(": ") \
), \ ), \
(msg) \ (msg) \
) \ ) \
); \ ); \
Local<Object> name ##_obj = name->ToObject(); \ Local<Object> name ##_obj = name->ToObject(); \
name ##_obj->Set(NODE_PSYMBOL("errno"), Integer::New(errno)); \ name ##_obj->Set(NanNew("errno"), NanNew<Integer>(errno)); \
name ##_obj->Set(NODE_PSYMBOL("code"), \ name ##_obj->Set(NanNew("code"), \
String::NewSymbol(sqlite_code_string(errno))); NanNew(sqlite_code_string(errno)));
#define EMIT_EVENT(obj, argc, argv) \ #define EMIT_EVENT(obj, argc, argv) \
TRY_CATCH_CALL((obj), \ TRY_CATCH_CALL((obj), \
Local<Function>::Cast((obj)->Get(String::NewSymbol("emit"))), \ Local<Function>::Cast((obj)->Get(NanNew("emit"))), \
argc, argv \ argc, argv \
); );
#define TRY_CATCH_CALL(context, callback, argc, argv) \ #define TRY_CATCH_CALL(context, callback, argc, argv) \
{ TryCatch try_catch; \ NanMakeCallback((context), (callback), (argc), (argv))
(callback)->Call((context), (argc), (argv)); \
if (try_catch.HasCaught()) { \
FatalException(try_catch); \
} }
#define WORK_DEFINITION(name) \ #define WORK_DEFINITION(name) \
static Handle<Value> name(const Arguments& args); \ static NAN_METHOD(name); \
static void Work_Begin##name(Baton* baton); \ static void Work_Begin##name(Baton* baton); \
static void Work_##name(uv_work_t* req); \ static void Work_##name(uv_work_t* req); \
static void Work_After##name(uv_work_t* req); static void Work_After##name(uv_work_t* req);
...@@ -164,4 +148,3 @@ const char* sqlite_authorizer_string(int type); ...@@ -164,4 +148,3 @@ const char* sqlite_authorizer_string(int type);
} }
#endif #endif
...@@ -16,6 +16,7 @@ using namespace node_sqlite3; ...@@ -16,6 +16,7 @@ using namespace node_sqlite3;
namespace { namespace {
void RegisterModule(v8::Handle<Object> target) { void RegisterModule(v8::Handle<Object> target) {
NanScope();
Database::Init(target); Database::Init(target);
Statement::Init(target); Statement::Init(target);
...@@ -103,4 +104,4 @@ const char* sqlite_authorizer_string(int type) { ...@@ -103,4 +104,4 @@ const char* sqlite_authorizer_string(int type) {
} }
} }
NODE_MODULE(node_sqlite3, RegisterModule); NODE_MODULE(node_sqlite3, RegisterModule)
...@@ -12,24 +12,24 @@ using namespace node_sqlite3; ...@@ -12,24 +12,24 @@ using namespace node_sqlite3;
Persistent<FunctionTemplate> Statement::constructor_template; Persistent<FunctionTemplate> Statement::constructor_template;
void Statement::Init(Handle<Object> target) { void Statement::Init(Handle<Object> target) {
HandleScope scope; NanScope();
Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
constructor_template = Persistent<FunctionTemplate>::New(t); t->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(NanNew("Statement"));
constructor_template->SetClassName(String::NewSymbol("Statement"));
NODE_SET_PROTOTYPE_METHOD(constructor_template, "bind", Bind); NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "get", Get); NODE_SET_PROTOTYPE_METHOD(t, "get", Get);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "run", Run); NODE_SET_PROTOTYPE_METHOD(t, "run", Run);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "all", All); NODE_SET_PROTOTYPE_METHOD(t, "all", All);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "each", Each); NODE_SET_PROTOTYPE_METHOD(t, "each", Each);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset); NODE_SET_PROTOTYPE_METHOD(t, "reset", Reset);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize); NODE_SET_PROTOTYPE_METHOD(t, "finalize", Finalize);
target->Set(String::NewSymbol("Statement"), NanAssignPersistent(constructor_template, t);
constructor_template->GetFunction()); target->Set(NanNew("Statement"),
t->GetFunction());
} }
void Statement::Process() { void Statement::Process() {
...@@ -60,50 +60,49 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) { ...@@ -60,50 +60,49 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) {
} }
template <class T> void Statement::Error(T* baton) { template <class T> void Statement::Error(T* baton) {
NanScope();
Statement* stmt = baton->stmt; Statement* stmt = baton->stmt;
// Fail hard on logic errors. // Fail hard on logic errors.
assert(stmt->status != 0); assert(stmt->status != 0);
EXCEPTION(String::New(stmt->message.c_str()), stmt->status, exception); EXCEPTION(NanNew<String>(stmt->message.c_str()), stmt->status, exception);
Local<Function> cb = NanNew(baton->callback);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
else { else {
Local<Value> argv[] = { String::NewSymbol("error"), exception }; Local<Value> argv[] = { NanNew("error"), exception };
EMIT_EVENT(stmt->handle_, 2, argv); EMIT_EVENT(NanObjectWrapHandle(stmt), 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) { NAN_METHOD(Statement::New) {
HandleScope scope; NanScope();
if (!args.IsConstructCall()) { if (!args.IsConstructCall()) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("Use the new operator to create new Statement objects");
String::New("Use the new operator to create new Statement objects"))
);
} }
int length = args.Length(); int length = args.Length();
if (length <= 0 || !Database::HasInstance(args[0])) { if (length <= 0 || !Database::HasInstance(args[0])) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("Database object expected");
String::New("Database object expected")));
} }
else if (length <= 1 || !args[1]->IsString()) { else if (length <= 1 || !args[1]->IsString()) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("SQL query expected");
String::New("SQL query expected")));
} }
else if (length > 2 && !args[2]->IsUndefined() && !args[2]->IsFunction()) { else if (length > 2 && !args[2]->IsUndefined() && !args[2]->IsFunction()) {
return ThrowException(Exception::TypeError( return NanThrowTypeError("Callback expected");
String::New("Callback expected")));
} }
Database* db = ObjectWrap::Unwrap<Database>(args[0]->ToObject()); Database* db = ObjectWrap::Unwrap<Database>(args[0]->ToObject());
Local<String> sql = Local<String>::Cast(args[1]); Local<String> sql = Local<String>::Cast(args[1]);
args.This()->Set(String::NewSymbol("sql"), sql, ReadOnly); args.This()->Set(NanNew("sql"), sql, ReadOnly);
Statement* stmt = new Statement(db); Statement* stmt = new Statement(db);
stmt->Wrap(args.This()); stmt->Wrap(args.This());
...@@ -112,7 +111,7 @@ Handle<Value> Statement::New(const Arguments& args) { ...@@ -112,7 +111,7 @@ Handle<Value> Statement::New(const Arguments& args) {
baton->sql = std::string(*String::Utf8Value(sql)); baton->sql = std::string(*String::Utf8Value(sql));
db->Schedule(Work_BeginPrepare, baton); db->Schedule(Work_BeginPrepare, baton);
return args.This(); NanReturnValue(args.This());
} }
void Statement::Work_BeginPrepare(Database::Baton* baton) { void Statement::Work_BeginPrepare(Database::Baton* baton) {
...@@ -128,27 +127,27 @@ void Statement::Work_Prepare(uv_work_t* req) { ...@@ -128,27 +127,27 @@ void Statement::Work_Prepare(uv_work_t* req) {
// In case preparing fails, we use a mutex to make sure we get the associated // In case preparing fails, we use a mutex to make sure we get the associated
// error message. // error message.
sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle);
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
stmt->status = sqlite3_prepare_v2( stmt->status = sqlite3_prepare_v2(
baton->db->handle, baton->db->_handle,
baton->sql.c_str(), baton->sql.c_str(),
baton->sql.size(), baton->sql.size(),
&stmt->handle, &stmt->_handle,
NULL NULL
); );
if (stmt->status != SQLITE_OK) { if (stmt->status != SQLITE_OK) {
stmt->message = std::string(sqlite3_errmsg(baton->db->handle)); stmt->message = std::string(sqlite3_errmsg(baton->db->_handle));
stmt->handle = NULL; stmt->_handle = NULL;
} }
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
} }
void Statement::Work_AfterPrepare(uv_work_t* req) { void Statement::Work_AfterPrepare(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(PrepareBaton); STATEMENT_INIT(PrepareBaton);
if (stmt->status != SQLITE_OK) { if (stmt->status != SQLITE_OK) {
...@@ -157,9 +156,10 @@ void Statement::Work_AfterPrepare(uv_work_t* req) { ...@@ -157,9 +156,10 @@ void Statement::Work_AfterPrepare(uv_work_t* req) {
} }
else { else {
stmt->prepared = true; stmt->prepared = true;
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
Local<Value> argv[] = { Local<Value>::New(Null()) }; if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
} }
...@@ -196,7 +196,9 @@ template <class T> Values::Field* ...@@ -196,7 +196,9 @@ template <class T> Values::Field*
} }
} }
template <class T> T* Statement::Bind(const Arguments& args, int start, int last) { template <class T> T* Statement::Bind(_NAN_METHOD_ARGS, int start, int last) {
NanScope();
if (last < 0) last = args.Length(); if (last < 0) last = args.Length();
Local<Function> callback; Local<Function> callback;
if (last > start && args[last - 1]->IsFunction()) { if (last > start && args[last - 1]->IsFunction()) {
...@@ -252,8 +254,8 @@ bool Statement::Bind(const Parameters & parameters) { ...@@ -252,8 +254,8 @@ bool Statement::Bind(const Parameters & parameters) {
return true; return true;
} }
sqlite3_reset(handle); sqlite3_reset(_handle);
sqlite3_clear_bindings(handle); sqlite3_clear_bindings(_handle);
Parameters::const_iterator it = parameters.begin(); Parameters::const_iterator it = parameters.begin();
Parameters::const_iterator end = parameters.end(); Parameters::const_iterator end = parameters.end();
...@@ -267,36 +269,36 @@ bool Statement::Bind(const Parameters & parameters) { ...@@ -267,36 +269,36 @@ bool Statement::Bind(const Parameters & parameters) {
pos = field->index; pos = field->index;
} }
else { else {
pos = sqlite3_bind_parameter_index(handle, field->name.c_str()); pos = sqlite3_bind_parameter_index(_handle, field->name.c_str());
} }
switch (field->type) { switch (field->type) {
case SQLITE_INTEGER: { case SQLITE_INTEGER: {
status = sqlite3_bind_int(handle, pos, status = sqlite3_bind_int(_handle, pos,
((Values::Integer*)field)->value); ((Values::Integer*)field)->value);
} break; } break;
case SQLITE_FLOAT: { case SQLITE_FLOAT: {
status = sqlite3_bind_double(handle, pos, status = sqlite3_bind_double(_handle, pos,
((Values::Float*)field)->value); ((Values::Float*)field)->value);
} break; } break;
case SQLITE_TEXT: { case SQLITE_TEXT: {
status = sqlite3_bind_text(handle, pos, status = sqlite3_bind_text(_handle, pos,
((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.c_str(),
((Values::Text*)field)->value.size(), SQLITE_TRANSIENT); ((Values::Text*)field)->value.size(), SQLITE_TRANSIENT);
} break; } break;
case SQLITE_BLOB: { case SQLITE_BLOB: {
status = sqlite3_bind_blob(handle, pos, status = sqlite3_bind_blob(_handle, pos,
((Values::Blob*)field)->value, ((Values::Blob*)field)->value,
((Values::Blob*)field)->length, SQLITE_TRANSIENT); ((Values::Blob*)field)->length, SQLITE_TRANSIENT);
} break; } break;
case SQLITE_NULL: { case SQLITE_NULL: {
status = sqlite3_bind_null(handle, pos); status = sqlite3_bind_null(_handle, pos);
} break; } break;
} }
} }
if (status != SQLITE_OK) { if (status != SQLITE_OK) {
message = std::string(sqlite3_errmsg(db->handle)); message = std::string(sqlite3_errmsg(db->_handle));
return false; return false;
} }
} }
...@@ -304,17 +306,17 @@ bool Statement::Bind(const Parameters & parameters) { ...@@ -304,17 +306,17 @@ bool Statement::Bind(const Parameters & parameters) {
return true; return true;
} }
Handle<Value> Statement::Bind(const Arguments& args) { NAN_METHOD(Statement::Bind) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
Baton* baton = stmt->Bind<Baton>(args); Baton* baton = stmt->Bind<Baton>(args);
if (baton == NULL) { if (baton == NULL) {
return ThrowException(Exception::Error(String::New("Data type is not supported"))); return NanThrowTypeError("Data type is not supported");
} }
else { else {
stmt->Schedule(Work_BeginBind, baton); stmt->Schedule(Work_BeginBind, baton);
return args.This(); NanReturnValue(args.This());
} }
} }
...@@ -325,14 +327,14 @@ void Statement::Work_BeginBind(Baton* baton) { ...@@ -325,14 +327,14 @@ void Statement::Work_BeginBind(Baton* baton) {
void Statement::Work_Bind(uv_work_t* req) { void Statement::Work_Bind(uv_work_t* req) {
STATEMENT_INIT(Baton); STATEMENT_INIT(Baton);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
stmt->Bind(baton->parameters); stmt->Bind(baton->parameters);
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
} }
void Statement::Work_AfterBind(uv_work_t* req) { void Statement::Work_AfterBind(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(Baton); STATEMENT_INIT(Baton);
if (stmt->status != SQLITE_OK) { if (stmt->status != SQLITE_OK) {
...@@ -340,9 +342,10 @@ void Statement::Work_AfterBind(uv_work_t* req) { ...@@ -340,9 +342,10 @@ void Statement::Work_AfterBind(uv_work_t* req) {
} }
else { else {
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
Local<Value> argv[] = { Local<Value>::New(Null()) }; if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
} }
...@@ -351,17 +354,17 @@ void Statement::Work_AfterBind(uv_work_t* req) { ...@@ -351,17 +354,17 @@ void Statement::Work_AfterBind(uv_work_t* req) {
Handle<Value> Statement::Get(const Arguments& args) { NAN_METHOD(Statement::Get) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
Baton* baton = stmt->Bind<RowBaton>(args); Baton* baton = stmt->Bind<RowBaton>(args);
if (baton == NULL) { if (baton == NULL) {
return ThrowException(Exception::Error(String::New("Data type is not supported"))); return NanThrowError("Data type is not supported");
} }
else { else {
stmt->Schedule(Work_BeginGet, baton); stmt->Schedule(Work_BeginGet, baton);
return args.This(); NanReturnValue(args.This());
} }
} }
...@@ -373,14 +376,14 @@ void Statement::Work_Get(uv_work_t* req) { ...@@ -373,14 +376,14 @@ void Statement::Work_Get(uv_work_t* req) {
STATEMENT_INIT(RowBaton); STATEMENT_INIT(RowBaton);
if (stmt->status != SQLITE_DONE || baton->parameters.size()) { if (stmt->status != SQLITE_DONE || baton->parameters.size()) {
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
if (stmt->Bind(baton->parameters)) { if (stmt->Bind(baton->parameters)) {
stmt->status = sqlite3_step(stmt->handle); stmt->status = sqlite3_step(stmt->_handle);
if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) { if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) {
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle)); stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
} }
} }
...@@ -388,13 +391,13 @@ void Statement::Work_Get(uv_work_t* req) { ...@@ -388,13 +391,13 @@ void Statement::Work_Get(uv_work_t* req) {
if (stmt->status == SQLITE_ROW) { if (stmt->status == SQLITE_ROW) {
// Acquire one result row before returning. // Acquire one result row before returning.
GetRow(&baton->row, stmt->handle); GetRow(&baton->row, stmt->_handle);
} }
} }
} }
void Statement::Work_AfterGet(uv_work_t* req) { void Statement::Work_AfterGet(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(RowBaton); STATEMENT_INIT(RowBaton);
if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
...@@ -402,15 +405,16 @@ void Statement::Work_AfterGet(uv_work_t* req) { ...@@ -402,15 +405,16 @@ void Statement::Work_AfterGet(uv_work_t* req) {
} }
else { else {
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
if (!cb.IsEmpty() && cb->IsFunction()) {
if (stmt->status == SQLITE_ROW) { if (stmt->status == SQLITE_ROW) {
// Create the result array from the data we acquired. // Create the result array from the data we acquired.
Local<Value> argv[] = { Local<Value>::New(Null()), RowToJS(&baton->row) }; Local<Value> argv[] = { NanNew(NanNull()), RowToJS(&baton->row) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv);
} }
else { else {
Local<Value> argv[] = { Local<Value>::New(Null()) }; Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
} }
} }
...@@ -418,17 +422,17 @@ void Statement::Work_AfterGet(uv_work_t* req) { ...@@ -418,17 +422,17 @@ void Statement::Work_AfterGet(uv_work_t* req) {
STATEMENT_END(); STATEMENT_END();
} }
Handle<Value> Statement::Run(const Arguments& args) { NAN_METHOD(Statement::Run) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
Baton* baton = stmt->Bind<RunBaton>(args); Baton* baton = stmt->Bind<RunBaton>(args);
if (baton == NULL) { if (baton == NULL) {
return ThrowException(Exception::Error(String::New("Data type is not supported"))); return NanThrowError("Data type is not supported");
} }
else { else {
stmt->Schedule(Work_BeginRun, baton); stmt->Schedule(Work_BeginRun, baton);
return args.This(); NanReturnValue(args.This());
} }
} }
...@@ -439,23 +443,23 @@ void Statement::Work_BeginRun(Baton* baton) { ...@@ -439,23 +443,23 @@ void Statement::Work_BeginRun(Baton* baton) {
void Statement::Work_Run(uv_work_t* req) { void Statement::Work_Run(uv_work_t* req) {
STATEMENT_INIT(RunBaton); STATEMENT_INIT(RunBaton);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
// Make sure that we also reset when there are no parameters. // Make sure that we also reset when there are no parameters.
if (!baton->parameters.size()) { if (!baton->parameters.size()) {
sqlite3_reset(stmt->handle); sqlite3_reset(stmt->_handle);
} }
if (stmt->Bind(baton->parameters)) { if (stmt->Bind(baton->parameters)) {
stmt->status = sqlite3_step(stmt->handle); stmt->status = sqlite3_step(stmt->_handle);
if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) { if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) {
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle)); stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
} }
else { else {
baton->inserted_id = sqlite3_last_insert_rowid(stmt->db->handle); baton->inserted_id = sqlite3_last_insert_rowid(stmt->db->_handle);
baton->changes = sqlite3_changes(stmt->db->handle); baton->changes = sqlite3_changes(stmt->db->_handle);
} }
} }
...@@ -463,7 +467,7 @@ void Statement::Work_Run(uv_work_t* req) { ...@@ -463,7 +467,7 @@ void Statement::Work_Run(uv_work_t* req) {
} }
void Statement::Work_AfterRun(uv_work_t* req) { void Statement::Work_AfterRun(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(RunBaton); STATEMENT_INIT(RunBaton);
if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
...@@ -471,29 +475,30 @@ void Statement::Work_AfterRun(uv_work_t* req) { ...@@ -471,29 +475,30 @@ void Statement::Work_AfterRun(uv_work_t* req) {
} }
else { else {
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
stmt->handle_->Set(String::NewSymbol("lastID"), Local<Integer>(Integer::New(baton->inserted_id))); if (!cb.IsEmpty() && cb->IsFunction()) {
stmt->handle_->Set(String::NewSymbol("changes"), Local<Integer>(Integer::New(baton->changes))); NanObjectWrapHandle(stmt)->Set(NanNew("lastID"), NanNew<Integer>(baton->inserted_id));
NanObjectWrapHandle(stmt)->Set(NanNew("changes"), NanNew<Integer>(baton->changes));
Local<Value> argv[] = { Local<Value>::New(Null()) }; Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
} }
STATEMENT_END(); STATEMENT_END();
} }
Handle<Value> Statement::All(const Arguments& args) { NAN_METHOD(Statement::All) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
Baton* baton = stmt->Bind<RowsBaton>(args); Baton* baton = stmt->Bind<RowsBaton>(args);
if (baton == NULL) { if (baton == NULL) {
return ThrowException(Exception::Error(String::New("Data type is not supported"))); return NanThrowError("Data type is not supported");
} }
else { else {
stmt->Schedule(Work_BeginAll, baton); stmt->Schedule(Work_BeginAll, baton);
return args.This(); NanReturnValue(args.This());
} }
} }
...@@ -504,23 +509,23 @@ void Statement::Work_BeginAll(Baton* baton) { ...@@ -504,23 +509,23 @@ void Statement::Work_BeginAll(Baton* baton) {
void Statement::Work_All(uv_work_t* req) { void Statement::Work_All(uv_work_t* req) {
STATEMENT_INIT(RowsBaton); STATEMENT_INIT(RowsBaton);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
// Make sure that we also reset when there are no parameters. // Make sure that we also reset when there are no parameters.
if (!baton->parameters.size()) { if (!baton->parameters.size()) {
sqlite3_reset(stmt->handle); sqlite3_reset(stmt->_handle);
} }
if (stmt->Bind(baton->parameters)) { if (stmt->Bind(baton->parameters)) {
while ((stmt->status = sqlite3_step(stmt->handle)) == SQLITE_ROW) { while ((stmt->status = sqlite3_step(stmt->_handle)) == SQLITE_ROW) {
Row* row = new Row(); Row* row = new Row();
GetRow(row, stmt->handle); GetRow(row, stmt->_handle);
baton->rows.push_back(row); baton->rows.push_back(row);
} }
if (stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_DONE) {
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle)); stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
} }
} }
...@@ -528,7 +533,7 @@ void Statement::Work_All(uv_work_t* req) { ...@@ -528,7 +533,7 @@ void Statement::Work_All(uv_work_t* req) {
} }
void Statement::Work_AfterAll(uv_work_t* req) { void Statement::Work_AfterAll(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(RowsBaton); STATEMENT_INIT(RowsBaton);
if (stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_DONE) {
...@@ -536,10 +541,11 @@ void Statement::Work_AfterAll(uv_work_t* req) { ...@@ -536,10 +541,11 @@ void Statement::Work_AfterAll(uv_work_t* req) {
} }
else { else {
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
if (!cb.IsEmpty() && cb->IsFunction()) {
if (baton->rows.size()) { if (baton->rows.size()) {
// Create the result array from the data we acquired. // Create the result array from the data we acquired.
Local<Array> result(Array::New(baton->rows.size())); Local<Array> result(NanNew<Array>(baton->rows.size()));
Rows::const_iterator it = baton->rows.begin(); Rows::const_iterator it = baton->rows.begin();
Rows::const_iterator end = baton->rows.end(); Rows::const_iterator end = baton->rows.end();
for (int i = 0; it < end; ++it, i++) { for (int i = 0; it < end; ++it, i++) {
...@@ -547,16 +553,16 @@ void Statement::Work_AfterAll(uv_work_t* req) { ...@@ -547,16 +553,16 @@ void Statement::Work_AfterAll(uv_work_t* req) {
delete *it; delete *it;
} }
Local<Value> argv[] = { Local<Value>::New(Null()), result }; Local<Value> argv[] = { NanNew(NanNull()), result };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv);
} }
else { else {
// There were no result rows. // There were no result rows.
Local<Value> argv[] = { Local<Value> argv[] = {
Local<Value>::New(Null()), NanNew(NanNull()),
Local<Value>::New(Array::New(0)) NanNew<Array>(0)
}; };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv);
} }
} }
} }
...@@ -564,8 +570,8 @@ void Statement::Work_AfterAll(uv_work_t* req) { ...@@ -564,8 +570,8 @@ void Statement::Work_AfterAll(uv_work_t* req) {
STATEMENT_END(); STATEMENT_END();
} }
Handle<Value> Statement::Each(const Arguments& args) { NAN_METHOD(Statement::Each) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
int last = args.Length(); int last = args.Length();
...@@ -577,12 +583,12 @@ Handle<Value> Statement::Each(const Arguments& args) { ...@@ -577,12 +583,12 @@ Handle<Value> Statement::Each(const Arguments& args) {
EachBaton* baton = stmt->Bind<EachBaton>(args, 0, last); EachBaton* baton = stmt->Bind<EachBaton>(args, 0, last);
if (baton == NULL) { if (baton == NULL) {
return ThrowException(Exception::Error(String::New("Data type is not supported"))); return NanThrowError("Data type is not supported");
} }
else { else {
baton->completed = Persistent<Function>::New(completed); NanAssignPersistent(baton->completed, completed);
stmt->Schedule(Work_BeginEach, baton); stmt->Schedule(Work_BeginEach, baton);
return args.This(); NanReturnValue(args.This());
} }
} }
...@@ -590,9 +596,9 @@ void Statement::Work_BeginEach(Baton* baton) { ...@@ -590,9 +596,9 @@ void Statement::Work_BeginEach(Baton* baton) {
// Only create the Async object when we're actually going into // Only create the Async object when we're actually going into
// the event loop. This prevents dangling events. // the event loop. This prevents dangling events.
EachBaton* each_baton = static_cast<EachBaton*>(baton); EachBaton* each_baton = static_cast<EachBaton*>(baton);
each_baton->async = new Async(each_baton->stmt, AsyncEach); each_baton->async = new Async(each_baton->stmt, reinterpret_cast<uv_async_cb>(AsyncEach));
each_baton->async->item_cb = Persistent<Function>::New(each_baton->callback); NanAssignPersistent(each_baton->async->item_cb, each_baton->callback);
each_baton->async->completed_cb = Persistent<Function>::New(each_baton->completed); NanAssignPersistent(each_baton->async->completed_cb, each_baton->completed);
STATEMENT_BEGIN(Each); STATEMENT_BEGIN(Each);
} }
...@@ -602,23 +608,23 @@ void Statement::Work_Each(uv_work_t* req) { ...@@ -602,23 +608,23 @@ void Statement::Work_Each(uv_work_t* req) {
Async* async = baton->async; Async* async = baton->async;
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
int retrieved = 0; int retrieved = 0;
// Make sure that we also reset when there are no parameters. // Make sure that we also reset when there are no parameters.
if (!baton->parameters.size()) { if (!baton->parameters.size()) {
sqlite3_reset(stmt->handle); sqlite3_reset(stmt->_handle);
} }
if (stmt->Bind(baton->parameters)) { if (stmt->Bind(baton->parameters)) {
while (true) { while (true) {
sqlite3_mutex_enter(mtx); sqlite3_mutex_enter(mtx);
stmt->status = sqlite3_step(stmt->handle); stmt->status = sqlite3_step(stmt->_handle);
if (stmt->status == SQLITE_ROW) { if (stmt->status == SQLITE_ROW) {
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
Row* row = new Row(); Row* row = new Row();
GetRow(row, stmt->handle); GetRow(row, stmt->_handle);
NODE_SQLITE3_MUTEX_LOCK(&async->mutex) NODE_SQLITE3_MUTEX_LOCK(&async->mutex)
async->data.push_back(row); async->data.push_back(row);
retrieved++; retrieved++;
...@@ -628,7 +634,7 @@ void Statement::Work_Each(uv_work_t* req) { ...@@ -628,7 +634,7 @@ void Statement::Work_Each(uv_work_t* req) {
} }
else { else {
if (stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_DONE) {
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle)); stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
} }
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
break; break;
...@@ -648,7 +654,7 @@ void Statement::CloseCallback(uv_handle_t* handle) { ...@@ -648,7 +654,7 @@ void Statement::CloseCallback(uv_handle_t* handle) {
} }
void Statement::AsyncEach(uv_async_t* handle, int status) { void Statement::AsyncEach(uv_async_t* handle, int status) {
HandleScope scope; NanScope();
Async* async = static_cast<Async*>(handle->data); Async* async = static_cast<Async*>(handle->data);
while (true) { while (true) {
...@@ -662,36 +668,38 @@ void Statement::AsyncEach(uv_async_t* handle, int status) { ...@@ -662,36 +668,38 @@ void Statement::AsyncEach(uv_async_t* handle, int status) {
break; break;
} }
if (!async->item_cb.IsEmpty() && async->item_cb->IsFunction()) { Local<Function> cb = NanNew(async->item_cb);
if (!cb.IsEmpty() && cb->IsFunction()) {
Local<Value> argv[2]; Local<Value> argv[2];
argv[0] = Local<Value>::New(Null()); argv[0] = NanNew(NanNull());
Rows::const_iterator it = rows.begin(); Rows::const_iterator it = rows.begin();
Rows::const_iterator end = rows.end(); Rows::const_iterator end = rows.end();
for (int i = 0; it < end; ++it, i++) { for (int i = 0; it < end; ++it, i++) {
argv[1] = RowToJS(*it); argv[1] = RowToJS(*it);
async->retrieved++; async->retrieved++;
TRY_CATCH_CALL(async->stmt->handle_, async->item_cb, 2, argv); TRY_CATCH_CALL(NanObjectWrapHandle(async->stmt), cb, 2, argv);
delete *it; delete *it;
} }
} }
} }
Local<Function> cb = NanNew(async->completed_cb);
if (async->completed) { if (async->completed) {
if (!async->completed_cb.IsEmpty() && if (!cb.IsEmpty() &&
async->completed_cb->IsFunction()) { cb->IsFunction()) {
Local<Value> argv[] = { Local<Value> argv[] = {
Local<Value>::New(Null()), NanNew(NanNull()),
Integer::New(async->retrieved) NanNew<Integer>(async->retrieved)
}; };
TRY_CATCH_CALL(async->stmt->handle_, async->completed_cb, 2, argv); TRY_CATCH_CALL(NanObjectWrapHandle(async->stmt), cb, 2, argv);
} }
uv_close((uv_handle_t*)handle, CloseCallback); uv_close((uv_handle_t*)handle, CloseCallback);
} }
} }
void Statement::Work_AfterEach(uv_work_t* req) { void Statement::Work_AfterEach(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(EachBaton); STATEMENT_INIT(EachBaton);
if (stmt->status != SQLITE_DONE) { if (stmt->status != SQLITE_DONE) {
...@@ -701,8 +709,8 @@ void Statement::Work_AfterEach(uv_work_t* req) { ...@@ -701,8 +709,8 @@ void Statement::Work_AfterEach(uv_work_t* req) {
STATEMENT_END(); STATEMENT_END();
} }
Handle<Value> Statement::Reset(const Arguments& args) { NAN_METHOD(Statement::Reset) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
...@@ -710,7 +718,7 @@ Handle<Value> Statement::Reset(const Arguments& args) { ...@@ -710,7 +718,7 @@ Handle<Value> Statement::Reset(const Arguments& args) {
Baton* baton = new Baton(stmt, callback); Baton* baton = new Baton(stmt, callback);
stmt->Schedule(Work_BeginReset, baton); stmt->Schedule(Work_BeginReset, baton);
return args.This(); NanReturnValue(args.This());
} }
void Statement::Work_BeginReset(Baton* baton) { void Statement::Work_BeginReset(Baton* baton) {
...@@ -720,25 +728,28 @@ void Statement::Work_BeginReset(Baton* baton) { ...@@ -720,25 +728,28 @@ void Statement::Work_BeginReset(Baton* baton) {
void Statement::Work_Reset(uv_work_t* req) { void Statement::Work_Reset(uv_work_t* req) {
STATEMENT_INIT(Baton); STATEMENT_INIT(Baton);
sqlite3_reset(stmt->handle); sqlite3_reset(stmt->_handle);
stmt->status = SQLITE_OK; stmt->status = SQLITE_OK;
} }
void Statement::Work_AfterReset(uv_work_t* req) { void Statement::Work_AfterReset(uv_work_t* req) {
HandleScope scope; NanScope();
STATEMENT_INIT(Baton); STATEMENT_INIT(Baton);
// Fire callbacks. // Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
Local<Value> argv[] = { Local<Value>::New(Null()) }; if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); Local<Value> argv[] = { NanNew(NanNull()) };
TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv);
} }
STATEMENT_END(); STATEMENT_END();
} }
Local<Object> Statement::RowToJS(Row* row) { Local<Object> Statement::RowToJS(Row* row) {
Local<Object> result(Object::New()); NanEscapableScope();
Local<Object> result(NanNew<Object>());
Row::const_iterator it = row->begin(); Row::const_iterator it = row->begin();
Row::const_iterator end = row->end(); Row::const_iterator end = row->end();
...@@ -749,32 +760,28 @@ Local<Object> Statement::RowToJS(Row* row) { ...@@ -749,32 +760,28 @@ Local<Object> Statement::RowToJS(Row* row) {
switch (field->type) { switch (field->type) {
case SQLITE_INTEGER: { case SQLITE_INTEGER: {
value = Local<Value>(Number::New(((Values::Integer*)field)->value)); value = NanNew<Number>(((Values::Integer*)field)->value);
} break; } break;
case SQLITE_FLOAT: { case SQLITE_FLOAT: {
value = Local<Value>(Number::New(((Values::Float*)field)->value)); value = NanNew<Number>(((Values::Float*)field)->value);
} break; } break;
case SQLITE_TEXT: { case SQLITE_TEXT: {
value = Local<Value>(String::New(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size())); value = NanNew<String>(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size());
} break; } break;
case SQLITE_BLOB: { case SQLITE_BLOB: {
#if NODE_VERSION_AT_LEAST(0, 11, 3) value = NanNew(NanNewBufferHandle(((Values::Blob*)field)->value, ((Values::Blob*)field)->length));
value = Local<Value>::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length));
#else
value = Local<Value>::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)->handle_);
#endif
} break; } break;
case SQLITE_NULL: { case SQLITE_NULL: {
value = Local<Value>::New(Null()); value = NanNew(NanNull());
} break; } break;
} }
result->Set(String::NewSymbol(field->name.c_str()), value); result->Set(NanNew(field->name.c_str()), value);
DELETE_FIELD(field); DELETE_FIELD(field);
} }
return result; return NanEscapeScope(result);
} }
void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { void Statement::GetRow(Row* row, sqlite3_stmt* stmt) {
...@@ -809,23 +816,25 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { ...@@ -809,23 +816,25 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) {
} }
} }
Handle<Value> Statement::Finalize(const Arguments& args) { NAN_METHOD(Statement::Finalize) {
HandleScope scope; NanScope();
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback); OPTIONAL_ARGUMENT_FUNCTION(0, callback);
Baton* baton = new Baton(stmt, callback); Baton* baton = new Baton(stmt, callback);
stmt->Schedule(Finalize, baton); stmt->Schedule(Finalize, baton);
return stmt->db->handle_; NanReturnValue(NanObjectWrapHandle(stmt->db));
} }
void Statement::Finalize(Baton* baton) { void Statement::Finalize(Baton* baton) {
NanScope();
baton->stmt->Finalize(); baton->stmt->Finalize();
// Fire callback in case there was one. // Fire callback in case there was one.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { Local<Function> cb = NanNew(baton->callback);
TRY_CATCH_CALL(baton->stmt->handle_, baton->callback, 0, NULL); if (!cb.IsEmpty() && cb->IsFunction()) {
TRY_CATCH_CALL(NanObjectWrapHandle(baton->stmt), cb, 0, NULL);
} }
delete baton; delete baton;
...@@ -837,16 +846,17 @@ void Statement::Finalize() { ...@@ -837,16 +846,17 @@ void Statement::Finalize() {
CleanQueue(); CleanQueue();
// Finalize returns the status code of the last operation. We already fired // Finalize returns the status code of the last operation. We already fired
// error events in case those failed. // error events in case those failed.
sqlite3_finalize(handle); sqlite3_finalize(_handle);
handle = NULL; _handle = NULL;
db->Unref(); db->Unref();
} }
void Statement::CleanQueue() { void Statement::CleanQueue() {
NanScope();
if (prepared && !queue.empty()) { if (prepared && !queue.empty()) {
// This statement has already been prepared and is now finalized. // This statement has already been prepared and is now finalized.
// Fire error for all remaining items in the queue. // Fire error for all remaining items in the queue.
EXCEPTION(String::New("Statement is already finalized"), SQLITE_MISUSE, exception); EXCEPTION(NanNew<String>("Statement is already finalized"), SQLITE_MISUSE, exception);
Local<Value> argv[] = { exception }; Local<Value> argv[] = { exception };
bool called = false; bool called = false;
...@@ -855,9 +865,11 @@ void Statement::CleanQueue() { ...@@ -855,9 +865,11 @@ void Statement::CleanQueue() {
Call* call = queue.front(); Call* call = queue.front();
queue.pop(); queue.pop();
if (prepared && !call->baton->callback.IsEmpty() && Local<Function> cb = NanNew(call->baton->callback);
call->baton->callback->IsFunction()) {
TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv); if (prepared && !cb.IsEmpty() &&
cb->IsFunction()) {
TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv);
called = true; called = true;
} }
...@@ -870,8 +882,8 @@ void Statement::CleanQueue() { ...@@ -870,8 +882,8 @@ void Statement::CleanQueue() {
// When we couldn't call a callback function, emit an error on the // When we couldn't call a callback function, emit an error on the
// Statement object. // Statement object.
if (!called) { if (!called) {
Local<Value> args[] = { String::NewSymbol("error"), exception }; Local<Value> args[] = { NanNew("error"), exception };
EMIT_EVENT(handle_, 2, args); EMIT_EVENT(NanObjectWrapHandle(this), 2, args);
} }
} }
else while (!queue.empty()) { else while (!queue.empty()) {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <vector> #include <vector>
#include <sqlite3.h> #include <sqlite3.h>
#include "nan.h"
using namespace v8; using namespace v8;
using namespace node; using namespace node;
...@@ -76,7 +77,7 @@ public: ...@@ -76,7 +77,7 @@ public:
static Persistent<FunctionTemplate> constructor_template; static Persistent<FunctionTemplate> constructor_template;
static void Init(Handle<Object> target); static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments& args); static NAN_METHOD(New);
struct Baton { struct Baton {
uv_work_t request; uv_work_t request;
...@@ -87,7 +88,7 @@ public: ...@@ -87,7 +88,7 @@ public:
Baton(Statement* stmt_, Handle<Function> cb_) : stmt(stmt_) { Baton(Statement* stmt_, Handle<Function> cb_) : stmt(stmt_) {
stmt->Ref(); stmt->Ref();
request.data = this; request.data = this;
callback = Persistent<Function>::New(cb_); NanAssignPersistent(callback, cb_);
} }
virtual ~Baton() { virtual ~Baton() {
for (unsigned int i = 0; i < parameters.size(); i++) { for (unsigned int i = 0; i < parameters.size(); i++) {
...@@ -95,7 +96,7 @@ public: ...@@ -95,7 +96,7 @@ public:
DELETE_FIELD(field); DELETE_FIELD(field);
} }
stmt->Unref(); stmt->Unref();
callback.Dispose(); NanDisposePersistent(callback);
} }
}; };
...@@ -175,15 +176,15 @@ public: ...@@ -175,15 +176,15 @@ public:
~Async() { ~Async() {
stmt->Unref(); stmt->Unref();
item_cb.Dispose(); NanDisposePersistent(item_cb);
completed_cb.Dispose(); NanDisposePersistent(completed_cb);
NODE_SQLITE3_MUTEX_DESTROY NODE_SQLITE3_MUTEX_DESTROY
} }
}; };
Statement(Database* db_) : ObjectWrap(), Statement(Database* db_) : ObjectWrap(),
db(db_), db(db_),
handle(NULL), _handle(NULL),
status(SQLITE_OK), status(SQLITE_OK),
prepared(false), prepared(false),
locked(true), locked(true),
...@@ -202,7 +203,7 @@ public: ...@@ -202,7 +203,7 @@ public:
WORK_DEFINITION(Each); WORK_DEFINITION(Each);
WORK_DEFINITION(Reset); WORK_DEFINITION(Reset);
static Handle<Value> Finalize(const Arguments& args); static NAN_METHOD(Finalize);
protected: protected:
static void Work_BeginPrepare(Database::Baton* baton); static void Work_BeginPrepare(Database::Baton* baton);
...@@ -216,8 +217,8 @@ protected: ...@@ -216,8 +217,8 @@ protected:
void Finalize(); void Finalize();
template <class T> inline Values::Field* BindParameter(const Handle<Value> source, T pos); template <class T> inline Values::Field* BindParameter(const Handle<Value> source, T pos);
template <class T> T* Bind(const Arguments& args, int start = 0, int end = -1); template <class T> T* Bind(_NAN_METHOD_ARGS, int start = 0, int end = -1);
bool Bind(const Parameters & parameters); bool Bind(const Parameters &parameters);
static void GetRow(Row* row, sqlite3_stmt* stmt); static void GetRow(Row* row, sqlite3_stmt* stmt);
static Local<Object> RowToJS(Row* row); static Local<Object> RowToJS(Row* row);
...@@ -229,7 +230,7 @@ protected: ...@@ -229,7 +230,7 @@ protected:
protected: protected:
Database* db; Database* db;
sqlite3_stmt* handle; sqlite3_stmt* _handle;
int status; int status;
std::string message; std::string message;
......
var sqlite3 = require('..'); var sqlite3 = require('..');
var assert = require('assert'); var assert = require('assert');
require('set-immediate');
describe('profiling', function() { describe('profiling', function() {
var create = false; var create = false;
...@@ -14,6 +15,7 @@ describe('profiling', function() { ...@@ -14,6 +15,7 @@ describe('profiling', function() {
if (sql.match(/^SELECT/)) { if (sql.match(/^SELECT/)) {
assert.ok(!select); assert.ok(!select);
assert.equal(sql, "SELECT * FROM foo"); assert.equal(sql, "SELECT * FROM foo");
console.log('profile select');
select = true; select = true;
} }
else if (sql.match(/^CREATE/)) { else if (sql.match(/^CREATE/)) {
...@@ -31,7 +33,7 @@ describe('profiling', function() { ...@@ -31,7 +33,7 @@ describe('profiling', function() {
assert.ok(!create); assert.ok(!create);
db.run("CREATE TABLE foo (id int)", function(err) { db.run("CREATE TABLE foo (id int)", function(err) {
if (err) throw err; if (err) throw err;
process.nextTick(function() { setImmediate(function() {
assert.ok(create); assert.ok(create);
done(); done();
}); });
...@@ -43,10 +45,10 @@ describe('profiling', function() { ...@@ -43,10 +45,10 @@ describe('profiling', function() {
assert.ok(!select); assert.ok(!select);
db.run("SELECT * FROM foo", function(err) { db.run("SELECT * FROM foo", function(err) {
if (err) throw err; if (err) throw err;
process.nextTick(function() { setImmediate(function() {
assert.ok(select); assert.ok(select);
done(); done();
}); }, 0);
}); });
}); });
......
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