Skip to content

Commit 2a01921

Browse files
author
Marc Schraffenberger
committed
added backup function to database object
1 parent ed7e649 commit 2a01921

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

src/database.cc

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ NAN_MODULE_INIT(Database::Init) {
2424
Nan::SetPrototypeMethod(t, "parallelize", Parallelize);
2525
Nan::SetPrototypeMethod(t, "configure", Configure);
2626
Nan::SetPrototypeMethod(t, "interrupt", Interrupt);
27+
Nan::SetPrototypeMethod(t, "backup", Backup);
2728

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

@@ -143,6 +144,7 @@ NAN_METHOD(Database::New) {
143144
void Database::Work_BeginOpen(Baton* baton) {
144145
int status = uv_queue_work(uv_default_loop(),
145146
&baton->request, Work_Open, (uv_after_work_cb)Work_AfterOpen);
147+
UNUSED_VARIABLE(status);
146148
assert(status == 0);
147149
}
148150

@@ -229,6 +231,7 @@ void Database::Work_BeginClose(Baton* baton) {
229231

230232
int status = uv_queue_work(uv_default_loop(),
231233
&baton->request, Work_Close, (uv_after_work_cb)Work_AfterClose);
234+
UNUSED_VARIABLE(status);
232235
assert(status == 0);
233236
}
234237

@@ -371,6 +374,83 @@ NAN_METHOD(Database::Interrupt) {
371374
info.GetReturnValue().Set(info.This());
372375
}
373376

377+
NAN_METHOD(Database::Backup) {
378+
Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
379+
380+
REQUIRE_ARGUMENT_STRING(0, filename);
381+
OPTIONAL_ARGUMENT_FUNCTION(1, callback);
382+
383+
Baton* baton = new BackupBaton(db, callback, *filename);
384+
db->Schedule(Work_BeginBackup, baton, false);
385+
386+
info.GetReturnValue().Set(info.This());
387+
}
388+
389+
void Database::Work_BeginBackup(Baton* baton) {
390+
assert(baton->db->open);
391+
assert(baton->db->_handle);
392+
int status = uv_queue_work(uv_default_loop(),
393+
&baton->request, Work_Backup, (uv_after_work_cb)Work_AfterExec);
394+
UNUSED_VARIABLE(status);
395+
assert(status == 0);
396+
}
397+
398+
void Database::Work_Backup(uv_work_t* req) {
399+
BackupBaton* baton = static_cast<BackupBaton*>(req->data);
400+
sqlite3* file;
401+
sqlite3_backup* backup;
402+
403+
baton->status = sqlite3_open(baton->filename.c_str(), &file);
404+
405+
if (baton->status == SQLITE_OK) {
406+
backup = sqlite3_backup_init(file, "main", baton->db->_handle, "main");
407+
408+
if (backup) {
409+
if (sqlite3_backup_step(backup, -1) == SQLITE_OK) {
410+
sqlite3_backup_finish(backup);
411+
}
412+
}
413+
414+
baton->status = sqlite3_errcode(file);
415+
}
416+
417+
sqlite3_close(file);
418+
419+
if (baton->status != SQLITE_OK) {
420+
baton->message = std::string(sqlite3_errmsg(file));
421+
}
422+
}
423+
424+
void Database::Work_AfterBackup(uv_work_t* req) {
425+
Nan::HandleScope scope;
426+
427+
BackupBaton* baton = static_cast<BackupBaton*>(req->data);
428+
Database* db = baton->db;
429+
430+
Local<Function> cb = Nan::New(baton->callback);
431+
432+
if (baton->status != SQLITE_OK) {
433+
EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
434+
435+
if (!cb.IsEmpty() && cb->IsFunction()) {
436+
Local<Value> argv[] = { exception };
437+
TRY_CATCH_CALL(db->handle(), cb, 1, argv);
438+
}
439+
else {
440+
Local<Value> info[] = { Nan::New("error").ToLocalChecked(), exception };
441+
EMIT_EVENT(db->handle(), 2, info);
442+
}
443+
}
444+
else if (!cb.IsEmpty() && cb->IsFunction()) {
445+
Local<Value> argv[] = { Nan::Null() };
446+
TRY_CATCH_CALL(db->handle(), cb, 1, argv);
447+
}
448+
449+
db->Process();
450+
451+
delete baton;
452+
}
453+
374454
void Database::SetBusyTimeout(Baton* baton) {
375455
assert(baton->db->open);
376456
assert(baton->db->_handle);
@@ -524,6 +604,7 @@ void Database::Work_BeginExec(Baton* baton) {
524604
assert(baton->db->pending == 0);
525605
int status = uv_queue_work(uv_default_loop(),
526606
&baton->request, Work_Exec, (uv_after_work_cb)Work_AfterExec);
607+
UNUSED_VARIABLE(status);
527608
assert(status == 0);
528609
}
529610

@@ -624,6 +705,7 @@ void Database::Work_BeginLoadExtension(Baton* baton) {
624705
assert(baton->db->pending == 0);
625706
int status = uv_queue_work(uv_default_loop(),
626707
&baton->request, Work_LoadExtension, reinterpret_cast<uv_after_work_cb>(Work_AfterLoadExtension));
708+
UNUSED_VARIABLE(status);
627709
assert(status == 0);
628710
}
629711

src/database.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ class Database : public Nan::ObjectWrap {
6868
Baton(db_, cb_), filename(filename_) {}
6969
};
7070

71+
struct BackupBaton : Baton {
72+
std::string filename;
73+
BackupBaton(Database* db_, Local<Function> cb_, const char* filename_) :
74+
Baton(db_, cb_), filename(filename_) {}
75+
};
76+
7177
typedef void (*Work_Callback)(Baton* baton);
7278

7379
struct Call {
@@ -154,6 +160,11 @@ class Database : public Nan::ObjectWrap {
154160

155161
static NAN_METHOD(Interrupt);
156162

163+
static NAN_METHOD(Backup);
164+
static void Work_BeginBackup(Baton* baton);
165+
static void Work_Backup(uv_work_t* req);
166+
static void Work_AfterBackup(uv_work_t* req);
167+
157168
static void SetBusyTimeout(Baton* baton);
158169

159170
static void RegisterTraceCallback(Baton* baton);

src/macros.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
const char* sqlite_code_string(int code);
55
const char* sqlite_authorizer_string(int type);
66

7+
#define UNUSED_VARIABLE(var) (void)var
78

89
#define REQUIRE_ARGUMENTS(n) \
910
if (info.Length() < (n)) { \

test/backup.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
var sqlite3 = require('..');
2+
var assert = require('assert');
3+
4+
describe('backup', function() {
5+
var db;
6+
before(function(done) {
7+
db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY, done);
8+
});
9+
10+
it('backup database', function(done) {
11+
db.backup('test/support/backup.db', done);
12+
});
13+
});
14+

0 commit comments

Comments
 (0)