Commit 3b410607 by Konstantin Käfer

first stab at 0.5.x compatibility

parent 9f039e82
var sqlite3 = module.exports = exports = require('./sqlite3_bindings'); var sqlite3 = module.exports = exports = require('./sqlite3_bindings.node');
var path = require('path'); var path = require('path');
var util = require('util');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var Database = sqlite3.Database; var Database = sqlite3.Database;
...@@ -148,6 +149,11 @@ Database.prototype.removeAllListeners = function(type) { ...@@ -148,6 +149,11 @@ Database.prototype.removeAllListeners = function(type) {
return val; return val;
}; };
Database.prototype.emit = EventEmitter.prototype.emit;
Database.prototype.once = EventEmitter.prototype.once;
// util.inherits(Database, EventEmitter);
// util.inherits(Statement, EventEmitter);
// Save the stack trace over EIO callbacks. // Save the stack trace over EIO callbacks.
sqlite3.verbose = function() { sqlite3.verbose = function() {
......
#include <string.h> #include <string.h>
#include <v8.h> #include <node/v8.h>
#include <node.h> #include <node/node.h>
#include <node_events.h>
#include "macros.h" #include "macros.h"
#include "database.h" #include "database.h"
...@@ -17,7 +16,6 @@ void Database::Init(Handle<Object> target) { ...@@ -17,7 +16,6 @@ void Database::Init(Handle<Object> target) {
Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = FunctionTemplate::New(New);
constructor_template = Persistent<FunctionTemplate>::New(t); constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->Inherit(EventEmitter::constructor_template);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1); constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Database")); constructor_template->SetClassName(String::NewSymbol("Database"));
...@@ -141,7 +139,7 @@ void Database::EIO_BeginOpen(Baton* baton) { ...@@ -141,7 +139,7 @@ void Database::EIO_BeginOpen(Baton* baton) {
eio_custom(EIO_Open, EIO_PRI_DEFAULT, EIO_AfterOpen, baton); eio_custom(EIO_Open, EIO_PRI_DEFAULT, EIO_AfterOpen, baton);
} }
int Database::EIO_Open(eio_req *req) { void Database::EIO_Open(eio_req *req) {
OpenBaton* baton = static_cast<OpenBaton*>(req->data); OpenBaton* baton = static_cast<OpenBaton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
...@@ -161,8 +159,6 @@ int Database::EIO_Open(eio_req *req) { ...@@ -161,8 +159,6 @@ int Database::EIO_Open(eio_req *req) {
// Set default database handle values. // Set default database handle values.
sqlite3_busy_timeout(db->handle, 1000); sqlite3_busy_timeout(db->handle, 1000);
} }
return 0;
} }
int Database::EIO_AfterOpen(eio_req *req) { int Database::EIO_AfterOpen(eio_req *req) {
...@@ -225,7 +221,7 @@ void Database::EIO_BeginClose(Baton* baton) { ...@@ -225,7 +221,7 @@ void Database::EIO_BeginClose(Baton* baton) {
eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton); eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
} }
int Database::EIO_Close(eio_req *req) { void Database::EIO_Close(eio_req *req) {
Baton* baton = static_cast<Baton*>(req->data); Baton* baton = static_cast<Baton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
...@@ -237,7 +233,6 @@ int Database::EIO_Close(eio_req *req) { ...@@ -237,7 +233,6 @@ int Database::EIO_Close(eio_req *req) {
else { else {
db->handle = NULL; db->handle = NULL;
} }
return 0;
} }
int Database::EIO_AfterClose(eio_req *req) { int Database::EIO_AfterClose(eio_req *req) {
...@@ -504,7 +499,7 @@ void Database::EIO_BeginExec(Baton* baton) { ...@@ -504,7 +499,7 @@ void Database::EIO_BeginExec(Baton* baton) {
eio_custom(EIO_Exec, EIO_PRI_DEFAULT, EIO_AfterExec, baton); eio_custom(EIO_Exec, EIO_PRI_DEFAULT, EIO_AfterExec, baton);
} }
int Database::EIO_Exec(eio_req *req) { void Database::EIO_Exec(eio_req *req) {
ExecBaton* baton = static_cast<ExecBaton*>(req->data); ExecBaton* baton = static_cast<ExecBaton*>(req->data);
char* message = NULL; char* message = NULL;
...@@ -520,8 +515,6 @@ int Database::EIO_Exec(eio_req *req) { ...@@ -520,8 +515,6 @@ int Database::EIO_Exec(eio_req *req) {
baton->message = std::string(message); baton->message = std::string(message);
sqlite3_free(message); sqlite3_free(message);
} }
return 0;
} }
int Database::EIO_AfterExec(eio_req *req) { int Database::EIO_AfterExec(eio_req *req) {
...@@ -574,7 +567,7 @@ void Database::EIO_BeginLoadExtension(Baton* baton) { ...@@ -574,7 +567,7 @@ void Database::EIO_BeginLoadExtension(Baton* baton) {
eio_custom(EIO_LoadExtension, EIO_PRI_DEFAULT, EIO_AfterLoadExtension, baton); eio_custom(EIO_LoadExtension, EIO_PRI_DEFAULT, EIO_AfterLoadExtension, baton);
} }
int Database::EIO_LoadExtension(eio_req *req) { void Database::EIO_LoadExtension(eio_req *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);
...@@ -593,8 +586,6 @@ int Database::EIO_LoadExtension(eio_req *req) { ...@@ -593,8 +586,6 @@ int Database::EIO_LoadExtension(eio_req *req) {
baton->message = std::string(message); baton->message = std::string(message);
sqlite3_free(message); sqlite3_free(message);
} }
return 0;
} }
int Database::EIO_AfterLoadExtension(eio_req *req) { int Database::EIO_AfterLoadExtension(eio_req *req) {
...@@ -673,13 +664,11 @@ void Database::Destruct(Persistent<Value> value, void *data) { ...@@ -673,13 +664,11 @@ void Database::Destruct(Persistent<Value> value, void *data) {
} }
} }
int Database::EIO_Destruct(eio_req *req) { void Database::EIO_Destruct(eio_req *req) {
Database* db = static_cast<Database*>(req->data); Database* db = static_cast<Database*>(req->data);
sqlite3_close(db->handle); sqlite3_close(db->handle);
db->handle = NULL; db->handle = NULL;
return 0;
} }
int Database::EIO_AfterDestruct(eio_req *req) { int Database::EIO_AfterDestruct(eio_req *req) {
......
#ifndef NODE_SQLITE3_SRC_DATABASE_H #ifndef NODE_SQLITE3_SRC_DATABASE_H
#define NODE_SQLITE3_SRC_DATABASE_H #define NODE_SQLITE3_SRC_DATABASE_H
#include <v8.h> #include <node/v8.h>
#include <node.h> #include <node/node.h>
#include <node_events.h>
#include <string> #include <string>
#include <queue> #include <queue>
...@@ -19,7 +18,7 @@ namespace node_sqlite3 { ...@@ -19,7 +18,7 @@ namespace node_sqlite3 {
class Database; class Database;
class Database : public EventEmitter { class Database : public ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor_template; static Persistent<FunctionTemplate> constructor_template;
static void Init(Handle<Object> target); static void Init(Handle<Object> target);
...@@ -100,7 +99,7 @@ public: ...@@ -100,7 +99,7 @@ public:
friend class Statement; friend class Statement;
protected: protected:
Database() : EventEmitter(), Database() : ObjectWrap(),
handle(NULL), handle(NULL),
open(false), open(false),
locked(false), locked(false),
...@@ -121,7 +120,7 @@ protected: ...@@ -121,7 +120,7 @@ protected:
static Handle<Value> New(const Arguments& args); static Handle<Value> New(const Arguments& args);
static void EIO_BeginOpen(Baton* baton); static void EIO_BeginOpen(Baton* baton);
static int EIO_Open(eio_req *req); static void EIO_Open(eio_req *req);
static int EIO_AfterOpen(eio_req *req); static int EIO_AfterOpen(eio_req *req);
static Handle<Value> OpenGetter(Local<String> str, const AccessorInfo& accessor); static Handle<Value> OpenGetter(Local<String> str, const AccessorInfo& accessor);
...@@ -131,17 +130,17 @@ protected: ...@@ -131,17 +130,17 @@ protected:
static Handle<Value> Exec(const Arguments& args); static Handle<Value> Exec(const Arguments& args);
static void EIO_BeginExec(Baton* baton); static void EIO_BeginExec(Baton* baton);
static int EIO_Exec(eio_req *req); static void EIO_Exec(eio_req *req);
static int EIO_AfterExec(eio_req *req); static int EIO_AfterExec(eio_req *req);
static Handle<Value> Close(const Arguments& args); static Handle<Value> Close(const Arguments& args);
static void EIO_BeginClose(Baton* baton); static void EIO_BeginClose(Baton* baton);
static int EIO_Close(eio_req *req); static void EIO_Close(eio_req *req);
static int EIO_AfterClose(eio_req *req); static int EIO_AfterClose(eio_req *req);
static Handle<Value> LoadExtension(const Arguments& args); static Handle<Value> LoadExtension(const Arguments& args);
static void EIO_BeginLoadExtension(Baton* baton); static void EIO_BeginLoadExtension(Baton* baton);
static int EIO_LoadExtension(eio_req *req); static void EIO_LoadExtension(eio_req *req);
static int EIO_AfterLoadExtension(eio_req *req); static int EIO_AfterLoadExtension(eio_req *req);
static Handle<Value> Serialize(const Arguments& args); static Handle<Value> Serialize(const Arguments& args);
...@@ -168,7 +167,7 @@ protected: ...@@ -168,7 +167,7 @@ protected:
inline void MakeWeak(); inline void MakeWeak();
virtual void Unref(); virtual void Unref();
static void Destruct (Persistent<Value> value, void *data); static void Destruct (Persistent<Value> value, void *data);
static int EIO_Destruct(eio_req *req); static void EIO_Destruct(eio_req *req);
static int EIO_AfterDestruct(eio_req *req); static int EIO_AfterDestruct(eio_req *req);
protected: protected:
......
...@@ -124,7 +124,7 @@ const char* sqlite_authorizer_string(int type); ...@@ -124,7 +124,7 @@ const char* sqlite_authorizer_string(int type);
#define EIO_DEFINITION(name) \ #define EIO_DEFINITION(name) \
static Handle<Value> name(const Arguments& args); \ static Handle<Value> name(const Arguments& args); \
static void EIO_Begin##name(Baton* baton); \ static void EIO_Begin##name(Baton* baton); \
static int EIO_##name(eio_req *req); \ static void EIO_##name(eio_req *req); \
static int EIO_After##name(eio_req *req); static int EIO_After##name(eio_req *req);
#define STATEMENT_BEGIN(type) \ #define STATEMENT_BEGIN(type) \
......
#include <v8.h> #include <v8.h>
#include <node.h> #include <node.h>
#include <node_events.h> #include <node_buffer.h>
#include <stdint.h>
#include <sstream>
#include <cstring>
#include <string>
#include <sqlite3.h> #include <sqlite3.h>
#include "macros.h" #include "macros.h"
...@@ -10,7 +14,9 @@ ...@@ -10,7 +14,9 @@
using namespace node_sqlite3; using namespace node_sqlite3;
extern "C" void init (v8::Handle<Object> target) { namespace {
void RegisterModule(v8::Handle<Object> target) {
Database::Init(target); Database::Init(target);
Statement::Init(target); Statement::Init(target);
...@@ -52,6 +58,8 @@ extern "C" void init (v8::Handle<Object> target) { ...@@ -52,6 +58,8 @@ extern "C" void init (v8::Handle<Object> target) {
DEFINE_CONSTANT_INTEGER(target, SQLITE_NOTADB, NOTADB); DEFINE_CONSTANT_INTEGER(target, SQLITE_NOTADB, NOTADB);
} }
}
const char* sqlite_code_string(int code) { const char* sqlite_code_string(int code) {
switch (code) { switch (code) {
case SQLITE_OK: return "SQLITE_OK"; case SQLITE_OK: return "SQLITE_OK";
...@@ -95,3 +103,5 @@ const char* sqlite_authorizer_string(int type) { ...@@ -95,3 +103,5 @@ const char* sqlite_authorizer_string(int type) {
default: return ""; default: return "";
} }
} }
NODE_MODULE(sqlite3_bindings, RegisterModule);
#include <string.h> #include <string.h>
#include <v8.h> #include <node/v8.h>
#include <node.h> #include <node/node.h>
#include <node_events.h> #include <node/node_buffer.h>
#include <node_buffer.h> #include <node/node_version.h>
#include <node_version.h>
#include "macros.h" #include "macros.h"
#include "database.h" #include "database.h"
...@@ -19,7 +18,6 @@ void Statement::Init(Handle<Object> target) { ...@@ -19,7 +18,6 @@ void Statement::Init(Handle<Object> target) {
Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = FunctionTemplate::New(New);
constructor_template = Persistent<FunctionTemplate>::New(t); constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->Inherit(EventEmitter::constructor_template);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1); constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Statement")); constructor_template->SetClassName(String::NewSymbol("Statement"));
...@@ -124,7 +122,7 @@ void Statement::EIO_BeginPrepare(Database::Baton* baton) { ...@@ -124,7 +122,7 @@ void Statement::EIO_BeginPrepare(Database::Baton* baton) {
eio_custom(EIO_Prepare, EIO_PRI_DEFAULT, EIO_AfterPrepare, baton); eio_custom(EIO_Prepare, EIO_PRI_DEFAULT, EIO_AfterPrepare, baton);
} }
int Statement::EIO_Prepare(eio_req *req) { void Statement::EIO_Prepare(eio_req *req) {
STATEMENT_INIT(PrepareBaton); STATEMENT_INIT(PrepareBaton);
// 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
...@@ -146,8 +144,6 @@ int Statement::EIO_Prepare(eio_req *req) { ...@@ -146,8 +144,6 @@ int Statement::EIO_Prepare(eio_req *req) {
} }
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
return 0;
} }
int Statement::EIO_AfterPrepare(eio_req *req) { int Statement::EIO_AfterPrepare(eio_req *req) {
...@@ -334,15 +330,13 @@ void Statement::EIO_BeginBind(Baton* baton) { ...@@ -334,15 +330,13 @@ void Statement::EIO_BeginBind(Baton* baton) {
STATEMENT_BEGIN(Bind); STATEMENT_BEGIN(Bind);
} }
int Statement::EIO_Bind(eio_req *req) { void Statement::EIO_Bind(eio_req *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);
return 0;
} }
int Statement::EIO_AfterBind(eio_req *req) { int Statement::EIO_AfterBind(eio_req *req) {
...@@ -384,7 +378,7 @@ void Statement::EIO_BeginGet(Baton* baton) { ...@@ -384,7 +378,7 @@ void Statement::EIO_BeginGet(Baton* baton) {
STATEMENT_BEGIN(Get); STATEMENT_BEGIN(Get);
} }
int Statement::EIO_Get(eio_req *req) { void Statement::EIO_Get(eio_req *req) {
STATEMENT_INIT(RowBaton); STATEMENT_INIT(RowBaton);
if (stmt->status != SQLITE_DONE || baton->parameters.size()) { if (stmt->status != SQLITE_DONE || baton->parameters.size()) {
...@@ -406,8 +400,6 @@ int Statement::EIO_Get(eio_req *req) { ...@@ -406,8 +400,6 @@ int Statement::EIO_Get(eio_req *req) {
GetRow(&baton->row, stmt->handle); GetRow(&baton->row, stmt->handle);
} }
} }
return 0;
} }
int Statement::EIO_AfterGet(eio_req *req) { int Statement::EIO_AfterGet(eio_req *req) {
...@@ -454,7 +446,7 @@ void Statement::EIO_BeginRun(Baton* baton) { ...@@ -454,7 +446,7 @@ void Statement::EIO_BeginRun(Baton* baton) {
STATEMENT_BEGIN(Run); STATEMENT_BEGIN(Run);
} }
int Statement::EIO_Run(eio_req *req) { void Statement::EIO_Run(eio_req *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);
...@@ -478,8 +470,6 @@ int Statement::EIO_Run(eio_req *req) { ...@@ -478,8 +470,6 @@ int Statement::EIO_Run(eio_req *req) {
} }
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
return 0;
} }
int Statement::EIO_AfterRun(eio_req *req) { int Statement::EIO_AfterRun(eio_req *req) {
...@@ -522,7 +512,7 @@ void Statement::EIO_BeginAll(Baton* baton) { ...@@ -522,7 +512,7 @@ void Statement::EIO_BeginAll(Baton* baton) {
STATEMENT_BEGIN(All); STATEMENT_BEGIN(All);
} }
int Statement::EIO_All(eio_req *req) { void Statement::EIO_All(eio_req *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);
...@@ -546,8 +536,6 @@ int Statement::EIO_All(eio_req *req) { ...@@ -546,8 +536,6 @@ int Statement::EIO_All(eio_req *req) {
} }
sqlite3_mutex_leave(mtx); sqlite3_mutex_leave(mtx);
return 0;
} }
int Statement::EIO_AfterAll(eio_req *req) { int Statement::EIO_AfterAll(eio_req *req) {
...@@ -605,6 +593,7 @@ Handle<Value> Statement::Each(const Arguments& args) { ...@@ -605,6 +593,7 @@ Handle<Value> Statement::Each(const Arguments& args) {
} }
else { else {
baton->completed = Persistent<Function>::New(completed); baton->completed = Persistent<Function>::New(completed);
baton->async = new Async(stmt, baton, AsyncEach);
stmt->Schedule(EIO_BeginEach, baton); stmt->Schedule(EIO_BeginEach, baton);
return args.This(); return args.This();
} }
...@@ -614,10 +603,11 @@ void Statement::EIO_BeginEach(Baton* baton) { ...@@ -614,10 +603,11 @@ void Statement::EIO_BeginEach(Baton* baton) {
STATEMENT_BEGIN(Each); STATEMENT_BEGIN(Each);
} }
int Statement::EIO_Each(eio_req *req) { void Statement::EIO_Each(eio_req *req) {
STATEMENT_INIT(EachBaton); STATEMENT_INIT(EachBaton);
Async* async = new Async(stmt, baton->callback, baton->completed, AsyncEach); Async* async = baton->async;
fprintf(stderr, "async:%p\n", async);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle); sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
...@@ -630,6 +620,7 @@ int Statement::EIO_Each(eio_req *req) { ...@@ -630,6 +620,7 @@ int Statement::EIO_Each(eio_req *req) {
if (stmt->Bind(baton->parameters)) { if (stmt->Bind(baton->parameters)) {
while (true) { while (true) {
fprintf(stderr, "before mutex\n");
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) {
...@@ -637,32 +628,39 @@ int Statement::EIO_Each(eio_req *req) { ...@@ -637,32 +628,39 @@ int Statement::EIO_Each(eio_req *req) {
Row* row = new Row(); Row* row = new Row();
GetRow(row, stmt->handle); GetRow(row, stmt->handle);
pthread_mutex_lock(&async->mutex); // pthread_mutex_lock(&async->mutex);
async->data.push_back(row); async->data.push_back(row);
retrieved++; retrieved++;
pthread_mutex_unlock(&async->mutex); // pthread_mutex_unlock(&async->mutex);
ev_async_send(EV_DEFAULT_ &async->watcher); fprintf(stderr, "retrieved:%d\n", retrieved);
// uv_async_send(&async->watcher);
} }
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);
fprintf(stderr, "done\n");
break; break;
} }
} }
} }
fprintf(stderr, "retrieved:%d\n", retrieved);
async->completed = true; async->completed = true;
ev_async_send(EV_DEFAULT_ &async->watcher); // uv_async_send(&async->watcher);
}
return 0; void Statement::CloseCallback(uv_handle_t* handle) {
assert(handle != NULL);
fprintf(stderr, "close callback\n");
} }
void Statement::AsyncEach(EV_P_ ev_async *w, int revents) { void Statement::AsyncEach(uv_async_t* handle, int status) {
HandleScope scope; HandleScope scope;
Async* async = static_cast<Async*>(w->data); Async* async = static_cast<Async*>(handle->data);
EachBaton* baton = async->baton;
while (true) { while (true) {
// Get the contents out of the data cache for us to process in the JS callback. // Get the contents out of the data cache for us to process in the JS callback.
...@@ -675,32 +673,34 @@ void Statement::AsyncEach(EV_P_ ev_async *w, int revents) { ...@@ -675,32 +673,34 @@ void Statement::AsyncEach(EV_P_ ev_async *w, int revents) {
break; break;
} }
if (!async->callback.IsEmpty() && async->callback->IsFunction()) { if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[2]; Local<Value> argv[2];
argv[0] = Local<Value>::New(Null()); argv[0] = Local<Value>::New(Null());
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->callback, 2, argv); // TRY_CATCH_CALL(async->stmt->handle_, baton->callback, 2, argv);
delete *it; // delete *it;
} }
} }
} }
if (async->completed) { if (async->completed) {
if (!async->completed_callback.IsEmpty() && fprintf(stderr, "completed\n");
async->completed_callback->IsFunction()) { if (!baton->completed.IsEmpty() &&
baton->completed->IsFunction()) {
Local<Value> argv[] = { Local<Value> argv[] = {
Local<Value>::New(Null()), Local<Value>::New(Null()),
Integer::New(async->retrieved) Integer::New(async->retrieved)
}; };
TRY_CATCH_CALL(async->stmt->handle_, async->completed_callback, 2, argv); TRY_CATCH_CALL(async->stmt->handle_, baton->completed, 2, argv);
} }
// uv_close((uv_handle_t*)handle, CloseCallback);
delete async; delete async;
w->data = NULL; handle->data = NULL;
} }
} }
...@@ -732,13 +732,11 @@ void Statement::EIO_BeginReset(Baton* baton) { ...@@ -732,13 +732,11 @@ void Statement::EIO_BeginReset(Baton* baton) {
STATEMENT_BEGIN(Reset); STATEMENT_BEGIN(Reset);
} }
int Statement::EIO_Reset(eio_req *req) { void Statement::EIO_Reset(eio_req *req) {
STATEMENT_INIT(Baton); STATEMENT_INIT(Baton);
sqlite3_reset(stmt->handle); sqlite3_reset(stmt->handle);
stmt->status = SQLITE_OK; stmt->status = SQLITE_OK;
return 0;
} }
int Statement::EIO_AfterReset(eio_req *req) { int Statement::EIO_AfterReset(eio_req *req) {
......
#ifndef NODE_SQLITE3_SRC_STATEMENT_H #ifndef NODE_SQLITE3_SRC_STATEMENT_H
#define NODE_SQLITE3_SRC_STATEMENT_H #define NODE_SQLITE3_SRC_STATEMENT_H
#include <v8.h> #include <node/v8.h>
#include <node.h> #include <node/node.h>
#include <node_events.h>
#include "database.h" #include "database.h"
...@@ -72,7 +71,7 @@ typedef Row Parameters; ...@@ -72,7 +71,7 @@ typedef Row Parameters;
class Statement : public EventEmitter { class Statement : public ObjectWrap {
public: public:
static Persistent<FunctionTemplate> constructor_template; static Persistent<FunctionTemplate> constructor_template;
...@@ -119,10 +118,13 @@ public: ...@@ -119,10 +118,13 @@ public:
Rows rows; Rows rows;
}; };
struct Async;
struct EachBaton : Baton { struct EachBaton : Baton {
EachBaton(Statement* stmt_, Handle<Function> cb_) : EachBaton(Statement* stmt_, Handle<Function> cb_) :
Baton(stmt_, cb_) {} Baton(stmt_, cb_) {}
Persistent<Function> completed; Persistent<Function> completed;
Async* async;
}; };
struct PrepareBaton : Database::Baton { struct PrepareBaton : Database::Baton {
...@@ -150,40 +152,33 @@ public: ...@@ -150,40 +152,33 @@ public:
Baton* baton; Baton* baton;
}; };
typedef void (*Async_Callback)(EV_P_ ev_async *w, int revents);
struct Async { struct Async {
ev_async watcher; uv_async_t watcher;
Statement* stmt; Statement* stmt;
EachBaton* baton;
Rows data; Rows data;
pthread_mutex_t mutex; pthread_mutex_t mutex;
Persistent<Function> callback;
bool completed; bool completed;
int retrieved; int retrieved;
Persistent<Function> completed_callback;
Async(Statement* st, Handle<Function> cb, Handle<Function>completed_cb, Async(Statement* st, EachBaton* eb, uv_async_cb async_cb) :
Async_Callback async_cb) : stmt(st), baton(eb), completed(false), retrieved(0) {
stmt(st), completed(false), retrieved(0) {
watcher.data = this; watcher.data = this;
ev_async_init(&watcher, async_cb);
ev_async_start(EV_DEFAULT_UC_ &watcher);
callback = Persistent<Function>::New(cb);
completed_callback = Persistent<Function>::New(completed_cb);
stmt->Ref();
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
fprintf(stderr, "initialized mutex\n");
stmt->Ref();
fprintf(stderr, "referenced stmt\n");
uv_async_init(uv_default_loop(), &watcher, async_cb);
fprintf(stderr, "started async\n");
} }
~Async() { ~Async() {
callback.Dispose();
completed_callback.Dispose();
stmt->Unref(); stmt->Unref();
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
ev_async_stop(EV_DEFAULT_UC_ &watcher);
} }
}; };
Statement(Database* db_) : EventEmitter(), Statement(Database* db_) : ObjectWrap(),
db(db_), db(db_),
handle(NULL), handle(NULL),
status(SQLITE_OK), status(SQLITE_OK),
...@@ -199,7 +194,7 @@ public: ...@@ -199,7 +194,7 @@ public:
protected: protected:
static void EIO_BeginPrepare(Database::Baton* baton); static void EIO_BeginPrepare(Database::Baton* baton);
static int EIO_Prepare(eio_req *req); static void EIO_Prepare(eio_req *req);
static int EIO_AfterPrepare(eio_req *req); static int EIO_AfterPrepare(eio_req *req);
EIO_DEFINITION(Bind); EIO_DEFINITION(Bind);
...@@ -209,7 +204,8 @@ protected: ...@@ -209,7 +204,8 @@ protected:
EIO_DEFINITION(Each); EIO_DEFINITION(Each);
EIO_DEFINITION(Reset); EIO_DEFINITION(Reset);
static void AsyncEach(EV_P_ ev_async *w, int revents); static void AsyncEach(uv_async_t* handle, int status);
static void CloseCallback(uv_handle_t* handle);
static Handle<Value> Finalize(const Arguments& args); static Handle<Value> Finalize(const Arguments& args);
static void Finalize(Baton* baton); static void Finalize(Baton* baton);
......
...@@ -19,24 +19,24 @@ exports['test Statement#each'] = function(beforeExit) { ...@@ -19,24 +19,24 @@ exports['test Statement#each'] = function(beforeExit) {
assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows."); assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows.");
}); });
}; };
//
exports['test Statement#each with complete callback'] = function(beforeExit) { // exports['test Statement#each with complete callback'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/big.db', sqlite3.OPEN_READONLY); // var db = new sqlite3.Database('test/support/big.db', sqlite3.OPEN_READONLY);
//
var total = 10000; // var total = 10000;
var retrieved = 0; // var retrieved = 0;
var completed = false; // var completed = false;
//
db.each('SELECT id, txt FROM foo LIMIT 0, ?', total, function(err, row) { // db.each('SELECT id, txt FROM foo LIMIT 0, ?', total, function(err, row) {
if (err) throw err; // if (err) throw err;
retrieved++; // retrieved++;
}, function(err, num) { // }, function(err, num) {
assert.equal(retrieved, num); // assert.equal(retrieved, num);
completed = true; // completed = true;
}); // });
//
beforeExit(function() { // beforeExit(function() {
assert.ok(completed); // assert.ok(completed);
assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows."); // assert.equal(retrieved, total, "Only retrieved " + retrieved + " out of " + total + " rows.");
}); // });
}; // };
#!/usr/bin/env python
import os import os
import sys import sys
import Options
from Configure import ConfigurationError
from os.path import exists from os.path import exists
from os import unlink
from shutil import copy2 as copy, rmtree from shutil import copy2 as copy, rmtree
# node-wafadmin # node-wafadmin
import Options import Options
import Utils import Utils
from Configure import ConfigurationError
TARGET = 'sqlite3_bindings' TARGET = 'sqlite3_bindings'
TARGET_FILE = '%s.node' % TARGET TARGET_FILE = '%s.node' % TARGET
built = 'build/default/%s' % TARGET_FILE built = 'build/Release/%s' % TARGET_FILE
dest = 'lib/%s' % TARGET_FILE dest = 'lib/%s' % TARGET_FILE
BUNDLED_SQLITE3_VERSION = '3070701' BUNDLED_SQLITE3_VERSION = '3070701'
...@@ -20,95 +21,103 @@ BUNDLED_SQLITE3 = 'sqlite-autoconf-%s' % BUNDLED_SQLITE3_VERSION ...@@ -20,95 +21,103 @@ BUNDLED_SQLITE3 = 'sqlite-autoconf-%s' % BUNDLED_SQLITE3_VERSION
BUNDLED_SQLITE3_TAR = 'sqlite-autoconf-%s.tar.gz' % BUNDLED_SQLITE3_VERSION BUNDLED_SQLITE3_TAR = 'sqlite-autoconf-%s.tar.gz' % BUNDLED_SQLITE3_VERSION
SQLITE3_TARGET = 'deps/%s' % BUNDLED_SQLITE3 SQLITE3_TARGET = 'deps/%s' % BUNDLED_SQLITE3
def set_options(opt):
opt.tool_options("compiler_cxx")
opt.add_option( '--internal-sqlite' def set_options(ctx):
, action='store_true' ctx.tool_options("compiler_cxx")
, default=True ctx.add_option('--internal-sqlite',
, help='Build dynamically against external install of libsqlite3 (default False - build uses internal copy)' action='store_true',
, dest='internal_sqlite' default=True,
) help='Build dynamically against external install of libsqlite3 (default False - build uses internal copy)',
dest='internal_sqlite')
def configure(conf):
conf.check_tool("compiler_cxx") def configure(ctx):
conf.check_tool("node_addon") ctx.check_tool('compiler_cxx')
ctx.check_tool('node_addon')
if not Options.options.internal_sqlite: if not Options.options.internal_sqlite:
try:
ctx.check_cfg(package="sqlite3",
args='--libs --cflags',
uselib_store="SQLITE3",
mandatory=True)
except ConfigurationError:
ctx.check(lib="sqlite3",
libpath=['/usr/local/lib', '/opt/local/lib'],
uselib_store="SQLITE3",
mandatory=True)
try: Utils.pprint('YELLOW','Note: pass --internal-sqlite to compile and link against bundled sqlite (version %s)' % BUNDLED_SQLITE3_VERSION)
conf.check_cfg(package="sqlite3", args='--libs --cflags',
uselib_store="SQLITE3", mandatory=True)
except ConfigurationError:
conf.check(lib="sqlite3", libpath=['/usr/local/lib', '/opt/local/lib'],
uselib_store="SQLITE3", mandatory=True)
Utils.pprint('YELLOW','Note: pass --internal-sqlite to compile and link against bundled sqlite (version %s)' % BUNDLED_SQLITE3_VERSION)
else: else:
configure_interal_sqlite3(conf) configure_interal_sqlite3(ctx)
linkflags = []
if os.environ.has_key('LINKFLAGS'): def configure_interal_sqlite3(ctx):
linkflags.extend(os.environ['LINKFLAGS'].split(' ')) os.chdir('deps')
if not os.path.exists(BUNDLED_SQLITE3):
if Options.options.internal_sqlite and Options.platform == 'darwin': os.system('tar xvf %s' % BUNDLED_SQLITE3_TAR)
linkflags.append('-Wl,-search_paths_first') os.chdir(BUNDLED_SQLITE3)
cxxflags = ''
conf.env.append_value("LINKFLAGS", linkflags) if os.environ.has_key('CFLAGS'):
cxxflags += os.environ['CFLAGS']
def configure_interal_sqlite3(conf): cxxflags += ' '
Utils.pprint('GREEN','Using internal sqlite3!') if os.environ.has_key('CXXFLAGS'):
cxxflags += os.environ['CXXFLAGS']
os.chdir('deps') # LINKFLAGS appear to be picked up automatically...
if not os.path.exists(BUNDLED_SQLITE3): if not os.path.exists('config.status'):
os.system('tar xvf %s' % BUNDLED_SQLITE3_TAR) Utils.pprint('GREEN','Configuring internal SQLite...')
os.chdir(BUNDLED_SQLITE3) os.system("CFLAGS='%s -DSQLITE_ENABLE_RTREE=1 -fPIC -O3 -DNDEBUG' ./configure --disable-dependency-tracking --enable-static --disable-shared" % cxxflags)
cxxflags = '' os.chdir('../../')
if os.environ.has_key('CFLAGS'):
cxxflags += os.environ['CFLAGS'] ctx.env.append_value("CPPPATH_SQLITE3", ['../deps/%s' % BUNDLED_SQLITE3])
cxxflags += ' ' ctx.env.append_value("LINKFLAGS", ['-L../deps/%s/.libs' % BUNDLED_SQLITE3, '-lsqlite3'])
if os.environ.has_key('CXXFLAGS'):
cxxflags += os.environ['CXXFLAGS'] sys.stderr.write('Configured internal SQLite : ')
# LINKFLAGS appear to be picked up automatically... Utils.pprint('GREEN', 'ok')
if not os.path.exists('config.status'):
os.system("CFLAGS='%s -DSQLITE_ENABLE_RTREE=1 -fPIC -O3 -DNDEBUG' ./configure --disable-dependency-tracking --enable-static --disable-shared" % cxxflags)
os.chdir('../../')
conf.env.append_value("CPPPATH_SQLITE3", ['../deps/%s' % BUNDLED_SQLITE3])
conf.env.append_value("LINKFLAGS", ['-L../deps/%s/.libs' % BUNDLED_SQLITE3, '-lsqlite3'])
def build_internal_sqlite3(): def build_internal_sqlite3():
if not Options.commands['clean'] and Options.options.internal_sqlite: if not Options.commands['clean'] and Options.options.internal_sqlite:
if not os.path.exists(SQLITE3_TARGET): if not os.path.exists(SQLITE3_TARGET):
Utils.pprint('RED','Please re-run ./configure or node-waf configure') Utils.pprint('RED','Please re-run ./configure or node-waf configure')
sys.exit() sys.exit()
os.chdir(SQLITE3_TARGET) os.chdir(SQLITE3_TARGET)
os.system('make') if not os.path.exists('libsqlite3.la'):
os.chdir('../../') Utils.pprint('GREEN','Building internal SQLite...')
os.system('make libsqlite3.la')
else:
Utils.pprint('GREEN','Internal SQLite already built.')
os.chdir('../../')
def clean_internal_sqlite3(): def clean_internal_sqlite3():
if os.path.exists(SQLITE3_TARGET): if os.path.exists(SQLITE3_TARGET):
rmtree(SQLITE3_TARGET) rmtree(SQLITE3_TARGET)
def build(bld):
obj = bld.new_task_gen("cxx", "shlib", "node_addon") def build(ctx):
build_internal_sqlite3() build_internal_sqlite3()
obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", t = ctx.new_task_gen('cxx', 'shlib', 'node_addon')
"-DSQLITE_ENABLE_RTREE=1", "-pthread", "-Wall"] t.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE",
# uncomment the next line to remove '-undefined dynamic_lookup' "-DSQLITE_ENABLE_RTREE=1", "-pthread", "-Wall"]
# uncomment the next line to remove '-undefined -dynamic_lookup'
# in order to review linker errors (v8, libev/eio references can be ignored) # in order to review linker errors (v8, libev/eio references can be ignored)
#obj.env['LINKFLAGS_MACBUNDLE'] = ['-bundle'] # t.env['LINKFLAGS_MACBUNDLE'] = ['-bundle']
obj.target = TARGET t.target = TARGET
obj.source = "src/sqlite3.cc src/database.cc src/statement.cc" t.source = "src/database.cc src/statement.cc src/sqlite3.cc"
obj.uselib = "SQLITE3" # t.uselib = "SQLITE3"
def clean(ctx):
if exists("build"):
rmtree("build")
if exists(dest):
unlink(dest)
clean_internal_sqlite3()
def shutdown(): def shutdown():
if Options.commands['clean']: if not Options.commands['clean'] and exists(built):
if exists(TARGET_FILE): copy(built, dest)
unlink(TARGET_FILE)
clean_internal_sqlite3()
else:
if exists(built):
copy(built, dest)
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