@@ -24,6 +24,7 @@ NAN_MODULE_INIT(Database::Init) {
24
24
Nan::SetPrototypeMethod (t, " parallelize" , Parallelize);
25
25
Nan::SetPrototypeMethod (t, " configure" , Configure);
26
26
Nan::SetPrototypeMethod (t, " interrupt" , Interrupt);
27
+ Nan::SetPrototypeMethod (t, " backup" , Backup);
27
28
28
29
NODE_SET_GETTER (t, " open" , OpenGetter);
29
30
@@ -143,6 +144,7 @@ NAN_METHOD(Database::New) {
143
144
void Database::Work_BeginOpen (Baton* baton) {
144
145
int status = uv_queue_work (uv_default_loop (),
145
146
&baton->request , Work_Open, (uv_after_work_cb)Work_AfterOpen);
147
+ UNUSED_VARIABLE (status);
146
148
assert (status == 0 );
147
149
}
148
150
@@ -229,6 +231,7 @@ void Database::Work_BeginClose(Baton* baton) {
229
231
230
232
int status = uv_queue_work (uv_default_loop (),
231
233
&baton->request , Work_Close, (uv_after_work_cb)Work_AfterClose);
234
+ UNUSED_VARIABLE (status);
232
235
assert (status == 0 );
233
236
}
234
237
@@ -371,6 +374,83 @@ NAN_METHOD(Database::Interrupt) {
371
374
info.GetReturnValue ().Set (info.This ());
372
375
}
373
376
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
+
374
454
void Database::SetBusyTimeout (Baton* baton) {
375
455
assert (baton->db ->open );
376
456
assert (baton->db ->_handle );
@@ -524,6 +604,7 @@ void Database::Work_BeginExec(Baton* baton) {
524
604
assert (baton->db ->pending == 0 );
525
605
int status = uv_queue_work (uv_default_loop (),
526
606
&baton->request , Work_Exec, (uv_after_work_cb)Work_AfterExec);
607
+ UNUSED_VARIABLE (status);
527
608
assert (status == 0 );
528
609
}
529
610
@@ -624,6 +705,7 @@ void Database::Work_BeginLoadExtension(Baton* baton) {
624
705
assert (baton->db ->pending == 0 );
625
706
int status = uv_queue_work (uv_default_loop (),
626
707
&baton->request , Work_LoadExtension, reinterpret_cast <uv_after_work_cb>(Work_AfterLoadExtension));
708
+ UNUSED_VARIABLE (status);
627
709
assert (status == 0 );
628
710
}
629
711
0 commit comments