Commit a76fbf83 by Konstantin Käfer

add extension loading support

parent 7ffb96ea
...@@ -23,6 +23,7 @@ void Database::Init(Handle<Object> target) { ...@@ -23,6 +23,7 @@ void Database::Init(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close); NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec); NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadExtension", LoadExtension);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize); NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize); NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure); NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure);
...@@ -437,6 +438,78 @@ int Database::EIO_AfterExec(eio_req *req) { ...@@ -437,6 +438,78 @@ int Database::EIO_AfterExec(eio_req *req) {
return 0; return 0;
} }
Handle<Value> Database::LoadExtension(const Arguments& args) {
HandleScope scope;
Database* db = ObjectWrap::Unwrap<Database>(args.This());
REQUIRE_ARGUMENT_STRING(0, filename);
OPTIONAL_ARGUMENT_FUNCTION(1, callback);
Baton* baton = new LoadExtensionBaton(db, callback, *filename);
db->Schedule(EIO_BeginLoadExtension, baton, true);
return args.This();
}
void Database::EIO_BeginLoadExtension(Baton* baton) {
assert(baton->db->locked);
assert(baton->db->open);
assert(baton->db->handle);
assert(baton->db->pending == 0);
eio_custom(EIO_LoadExtension, EIO_PRI_DEFAULT, EIO_AfterLoadExtension, baton);
}
int Database::EIO_LoadExtension(eio_req *req) {
LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
sqlite3_enable_load_extension(baton->db->handle, 1);
char* message = NULL;
baton->status = sqlite3_load_extension(
baton->db->handle,
baton->filename.c_str(),
0,
&message
);
sqlite3_enable_load_extension(baton->db->handle, 0);
if (baton->status != SQLITE_OK && message != NULL) {
baton->message = std::string(message);
sqlite3_free(message);
}
return 0;
}
int Database::EIO_AfterLoadExtension(eio_req *req) {
HandleScope scope;
LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
Database* db = baton->db;
if (baton->status != SQLITE_OK) {
EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { exception };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
}
else {
Local<Value> args[] = { String::NewSymbol("error"), exception };
EMIT_EVENT(db->handle_, 2, args);
}
}
else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) };
TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
}
db->Process();
delete baton;
return 0;
}
/** /**
* Override this so that we can properly close the database when this object * Override this so that we can properly close the database when this object
* gets garbage collected. * gets garbage collected.
......
...@@ -61,6 +61,12 @@ public: ...@@ -61,6 +61,12 @@ public:
Baton(db_, cb_), sql(sql_) {} Baton(db_, cb_), sql(sql_) {}
}; };
struct LoadExtensionBaton : Baton {
std::string filename;
LoadExtensionBaton(Database* db_, Handle<Function> cb_, const char* filename_) :
Baton(db_, cb_), filename(filename_) {}
};
typedef void (*EIO_Callback)(Baton* baton); typedef void (*EIO_Callback)(Baton* baton);
struct Call { struct Call {
...@@ -161,6 +167,11 @@ protected: ...@@ -161,6 +167,11 @@ protected:
static int EIO_Close(eio_req *req); static int 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 void EIO_BeginLoadExtension(Baton* baton);
static int EIO_LoadExtension(eio_req *req);
static int EIO_AfterLoadExtension(eio_req *req);
static Handle<Value> Serialize(const Arguments& args); static Handle<Value> Serialize(const Arguments& args);
static Handle<Value> Parallelize(const Arguments& args); static Handle<Value> Parallelize(const Arguments& args);
......
var sqlite3 = require('sqlite3');
var assert = require('assert');
if (process.setMaxListeners) process.setMaxListeners(0);
exports['test loadExtension'] = function(beforeExit) {
var db = new sqlite3.Database(':memory:');
var completed = false;
db.loadExtension('/usr/local/lib/libspatialite.dylib', function(err) {
if (err) throw err;
completed = true;
});
beforeExit(function() {
assert.ok(completed);
});
}
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