Skip to content

Commit 1bcbf70

Browse files
authored
Added support for setting SQLite limits
1 parent 61194ec commit 1bcbf70

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

src/database.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,22 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) {
371371
baton->status = info[1].As<Napi::Number>().Int32Value();
372372
db->Schedule(SetBusyTimeout, baton);
373373
}
374+
else if (info[0].StrictEquals( Napi::String::New(env, "limit"))) {
375+
REQUIRE_ARGUMENTS(3);
376+
if (!info[1].IsNumber()) {
377+
Napi::TypeError::New(env, "limit id must be an integer").ThrowAsJavaScriptException();
378+
return env.Null();
379+
}
380+
if (!info[2].IsNumber()) {
381+
Napi::TypeError::New(env, "limit value must be an integer").ThrowAsJavaScriptException();
382+
return env.Null();
383+
}
384+
Napi::Function handle;
385+
int id = info[1].As<Napi::Number>().Int32Value();
386+
int value = info[2].As<Napi::Number>().Int32Value();
387+
Baton* baton = new LimitBaton(db, handle, id, value);
388+
db->Schedule(SetLimit, baton);
389+
}
374390
else {
375391
Napi::TypeError::New(env, (StringConcat(
376392
#if V8_MAJOR_VERSION > 6
@@ -415,6 +431,15 @@ void Database::SetBusyTimeout(Baton* b) {
415431
sqlite3_busy_timeout(baton->db->_handle, baton->status);
416432
}
417433

434+
void Database::SetLimit(Baton* b) {
435+
std::unique_ptr<LimitBaton> baton(static_cast<LimitBaton*>(b));
436+
437+
assert(baton->db->open);
438+
assert(baton->db->_handle);
439+
440+
sqlite3_limit(baton->db->_handle, baton->id, baton->value);
441+
}
442+
418443
void Database::RegisterTraceCallback(Baton* b) {
419444
std::unique_ptr<Baton> baton(b);
420445
assert(baton->db->open);

src/database.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ class Database : public Napi::ObjectWrap<Database> {
8080
Baton(db_, cb_), filename(filename_) {}
8181
};
8282

83+
struct LimitBaton : Baton {
84+
int id;
85+
int value;
86+
LimitBaton(Database* db_, Napi::Function cb_, int id_, int value_) :
87+
Baton(db_, cb_), id(id_), value(value_) {}
88+
};
89+
8390
typedef void (*Work_Callback)(Baton* baton);
8491

8592
struct Call {
@@ -169,6 +176,7 @@ class Database : public Napi::ObjectWrap<Database> {
169176
Napi::Value Interrupt(const Napi::CallbackInfo& info);
170177

171178
static void SetBusyTimeout(Baton* baton);
179+
static void SetLimit(Baton* baton);
172180

173181
static void RegisterTraceCallback(Baton* baton);
174182
static void TraceCallback(void* db, const char* sql);

src/node_sqlite3.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ Napi::Object RegisterModule(Napi::Env env, Napi::Object exports) {
6161
DEFINE_CONSTANT_INTEGER(exports, SQLITE_FORMAT, FORMAT)
6262
DEFINE_CONSTANT_INTEGER(exports, SQLITE_RANGE, RANGE)
6363
DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOTADB, NOTADB)
64+
65+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LENGTH, LIMIT_LENGTH)
66+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_SQL_LENGTH, LIMIT_SQL_LENGTH)
67+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COLUMN, LIMIT_COLUMN)
68+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_EXPR_DEPTH, LIMIT_EXPR_DEPTH)
69+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COMPOUND_SELECT, LIMIT_COMPOUND_SELECT)
70+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VDBE_OP, LIMIT_VDBE_OP)
71+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_FUNCTION_ARG, LIMIT_FUNCTION_ARG)
72+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_ATTACHED, LIMIT_ATTACHED)
73+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, LIMIT_LIKE_PATTERN_LENGTH)
74+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VARIABLE_NUMBER, LIMIT_VARIABLE_NUMBER)
75+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_TRIGGER_DEPTH, LIMIT_TRIGGER_DEPTH)
76+
DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_WORKER_THREADS, LIMIT_WORKER_THREADS)
6477
});
6578

6679
return exports;

test/limit.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
var sqlite3 = require('..');
2+
3+
describe('limit', function() {
4+
var db;
5+
6+
before(function(done) {
7+
db = new sqlite3.Database(':memory:', done);
8+
});
9+
10+
it('should support applying limits via configure', function(done) {
11+
db.configure('limit', sqlite3.LIMIT_ATTACHED, 0);
12+
db.exec("ATTACH 'test/support/prepare.db' AS zing", function(err) {
13+
if (!err) {
14+
throw new Error('ATTACH should not succeed');
15+
}
16+
if (err.errno === sqlite3.ERROR &&
17+
err.message === 'SQLITE_ERROR: too many attached databases - max 0') {
18+
db.configure('limit', sqlite3.LIMIT_ATTACHED, 1);
19+
db.exec("ATTACH 'test/support/prepare.db' AS zing", function(err) {
20+
if (err) throw err;
21+
db.close(done);
22+
});
23+
} else {
24+
throw err;
25+
}
26+
});
27+
});
28+
});

0 commit comments

Comments
 (0)