Skip to content

Commit

Permalink
Merge pull request #518 from briangreenery/master
Browse files Browse the repository at this point in the history
Add support for sqlite3_interrupt
  • Loading branch information
Dane Springmeyer committed Apr 21, 2016
2 parents 96da7da + 8b0bb91 commit 68dcc13
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/database.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ NAN_MODULE_INIT(Database::Init) {
Nan::SetPrototypeMethod(t, "serialize", Serialize);
Nan::SetPrototypeMethod(t, "parallelize", Parallelize);
Nan::SetPrototypeMethod(t, "configure", Configure);
Nan::SetPrototypeMethod(t, "interrupt", Interrupt);

NODE_SET_GETTER(t, "open", OpenGetter);

Expand Down Expand Up @@ -224,6 +225,8 @@ void Database::Work_BeginClose(Baton* baton) {
assert(baton->db->pending == 0);

baton->db->RemoveCallbacks();
baton->db->closing = true;

int status = uv_queue_work(uv_default_loop(),
&baton->request, Work_Close, (uv_after_work_cb)Work_AfterClose);
assert(status == 0);
Expand All @@ -249,6 +252,8 @@ void Database::Work_AfterClose(uv_work_t* req) {
Baton* baton = static_cast<Baton*>(req->data);
Database* db = baton->db;

db->closing = false;

Local<Value> argv[1];
if (baton->status != SQLITE_OK) {
EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
Expand Down Expand Up @@ -351,6 +356,21 @@ NAN_METHOD(Database::Configure) {
info.GetReturnValue().Set(info.This());
}

NAN_METHOD(Database::Interrupt) {
Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());

if (!db->open) {
return Nan::ThrowError("Database is not open");
}

if (db->closing) {
return Nan::ThrowError("Database is closing");
}

sqlite3_interrupt(db->_handle);
info.GetReturnValue().Set(info.This());
}

void Database::SetBusyTimeout(Baton* baton) {
assert(baton->db->open);
assert(baton->db->_handle);
Expand Down
4 changes: 4 additions & 0 deletions src/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class Database : public Nan::ObjectWrap {
_handle(NULL),
open(false),
locked(false),
closing(false),
pending(0),
serialize(false),
debug_trace(NULL),
Expand Down Expand Up @@ -151,6 +152,8 @@ class Database : public Nan::ObjectWrap {

static NAN_METHOD(Configure);

static NAN_METHOD(Interrupt);

static void SetBusyTimeout(Baton* baton);

static void RegisterTraceCallback(Baton* baton);
Expand All @@ -171,6 +174,7 @@ class Database : public Nan::ObjectWrap {
sqlite3* _handle;

bool open;
bool closing;
bool locked;
unsigned int pending;

Expand Down
69 changes: 69 additions & 0 deletions test/interrupt.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
var sqlite3 = require('..');
var assert = require('assert');

describe('interrupt', function() {
it('should interrupt queries', function(done) {
var query =
'with t (n) as (values (1),(2),(3),(4),(5),(6),(7),(8)) ' +
'select last.n ' +
'from t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t as last';

var interrupted = false;
var saved = null;

var db = new sqlite3.Database(':memory:', function() {
db.each(query, function(err) {
if (!interrupted) {
interrupted = true;
db.interrupt();
} else if (err) {
saved = err;
}
});

db.close(function() {
if (saved) {
assert.equal(saved.message, 'SQLITE_INTERRUPT: interrupted');
assert.equal(saved.errno, sqlite3.INTERRUPT);
assert.equal(saved.code, 'SQLITE_INTERRUPT');
done();
} else {
done(new Error('Completed query without error, but expected error'));
}
});
});
});

it('should throw if interrupt is called before open', function(done) {
var db = new sqlite3.Database(':memory:');

assert.throws(function() {
db.interrupt();
}, (/Database is not open/));

db.close();
done();
});

it('should throw if interrupt is called after close', function(done) {
var db = new sqlite3.Database(':memory:');

db.close(function() {
assert.throws(function() {
db.interrupt();
}, (/Database is not open/));

done();
});
});

it('should throw if interrupt is called during close', function(done) {
var db = new sqlite3.Database(':memory:', function() {
db.close();
assert.throws(function() {
db.interrupt();
}, (/Database is closing/));
done();
});
});
});

0 comments on commit 68dcc13

Please sign in to comment.