Skip to content

Commit 68dcc13

Browse files
author
Dane Springmeyer
committed
Merge pull request #518 from briangreenery/master
Add support for sqlite3_interrupt
2 parents 96da7da + 8b0bb91 commit 68dcc13

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

src/database.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ NAN_MODULE_INIT(Database::Init) {
2323
Nan::SetPrototypeMethod(t, "serialize", Serialize);
2424
Nan::SetPrototypeMethod(t, "parallelize", Parallelize);
2525
Nan::SetPrototypeMethod(t, "configure", Configure);
26+
Nan::SetPrototypeMethod(t, "interrupt", Interrupt);
2627

2728
NODE_SET_GETTER(t, "open", OpenGetter);
2829

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

226227
baton->db->RemoveCallbacks();
228+
baton->db->closing = true;
229+
227230
int status = uv_queue_work(uv_default_loop(),
228231
&baton->request, Work_Close, (uv_after_work_cb)Work_AfterClose);
229232
assert(status == 0);
@@ -249,6 +252,8 @@ void Database::Work_AfterClose(uv_work_t* req) {
249252
Baton* baton = static_cast<Baton*>(req->data);
250253
Database* db = baton->db;
251254

255+
db->closing = false;
256+
252257
Local<Value> argv[1];
253258
if (baton->status != SQLITE_OK) {
254259
EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
@@ -351,6 +356,21 @@ NAN_METHOD(Database::Configure) {
351356
info.GetReturnValue().Set(info.This());
352357
}
353358

359+
NAN_METHOD(Database::Interrupt) {
360+
Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
361+
362+
if (!db->open) {
363+
return Nan::ThrowError("Database is not open");
364+
}
365+
366+
if (db->closing) {
367+
return Nan::ThrowError("Database is closing");
368+
}
369+
370+
sqlite3_interrupt(db->_handle);
371+
info.GetReturnValue().Set(info.This());
372+
}
373+
354374
void Database::SetBusyTimeout(Baton* baton) {
355375
assert(baton->db->open);
356376
assert(baton->db->_handle);

src/database.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class Database : public Nan::ObjectWrap {
104104
_handle(NULL),
105105
open(false),
106106
locked(false),
107+
closing(false),
107108
pending(0),
108109
serialize(false),
109110
debug_trace(NULL),
@@ -151,6 +152,8 @@ class Database : public Nan::ObjectWrap {
151152

152153
static NAN_METHOD(Configure);
153154

155+
static NAN_METHOD(Interrupt);
156+
154157
static void SetBusyTimeout(Baton* baton);
155158

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

173176
bool open;
177+
bool closing;
174178
bool locked;
175179
unsigned int pending;
176180

test/interrupt.test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
var sqlite3 = require('..');
2+
var assert = require('assert');
3+
4+
describe('interrupt', function() {
5+
it('should interrupt queries', function(done) {
6+
var query =
7+
'with t (n) as (values (1),(2),(3),(4),(5),(6),(7),(8)) ' +
8+
'select last.n ' +
9+
'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';
10+
11+
var interrupted = false;
12+
var saved = null;
13+
14+
var db = new sqlite3.Database(':memory:', function() {
15+
db.each(query, function(err) {
16+
if (!interrupted) {
17+
interrupted = true;
18+
db.interrupt();
19+
} else if (err) {
20+
saved = err;
21+
}
22+
});
23+
24+
db.close(function() {
25+
if (saved) {
26+
assert.equal(saved.message, 'SQLITE_INTERRUPT: interrupted');
27+
assert.equal(saved.errno, sqlite3.INTERRUPT);
28+
assert.equal(saved.code, 'SQLITE_INTERRUPT');
29+
done();
30+
} else {
31+
done(new Error('Completed query without error, but expected error'));
32+
}
33+
});
34+
});
35+
});
36+
37+
it('should throw if interrupt is called before open', function(done) {
38+
var db = new sqlite3.Database(':memory:');
39+
40+
assert.throws(function() {
41+
db.interrupt();
42+
}, (/Database is not open/));
43+
44+
db.close();
45+
done();
46+
});
47+
48+
it('should throw if interrupt is called after close', function(done) {
49+
var db = new sqlite3.Database(':memory:');
50+
51+
db.close(function() {
52+
assert.throws(function() {
53+
db.interrupt();
54+
}, (/Database is not open/));
55+
56+
done();
57+
});
58+
});
59+
60+
it('should throw if interrupt is called during close', function(done) {
61+
var db = new sqlite3.Database(':memory:', function() {
62+
db.close();
63+
assert.throws(function() {
64+
db.interrupt();
65+
}, (/Database is closing/));
66+
done();
67+
});
68+
});
69+
});

0 commit comments

Comments
 (0)