From 32828e03be0489572ab334239c5768c86697989f Mon Sep 17 00:00:00 2001 From: Fedor Indutnyy Date: Wed, 20 Oct 2021 11:32:50 -0700 Subject: [PATCH] Log corruption error information --- lib/database.js | 2 ++ src/better_sqlite3.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++ src/better_sqlite3.hpp | 1 + 3 files changed, 46 insertions(+) diff --git a/lib/database.js b/lib/database.js index 8c437c64..8daa4b86 100644 --- a/lib/database.js +++ b/lib/database.js @@ -6,6 +6,7 @@ const util = require('./util'); const { Database: CPPDatabase, setErrorConstructor, + setCorruptionLogger, } = require('bindings')('better_sqlite3.node'); function Database(filenameGiven, options) { @@ -61,6 +62,7 @@ Database.prototype.close = wrappers.close; Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers; Database.prototype.unsafeMode = wrappers.unsafeMode; Database.prototype[util.inspect] = require('./methods/inspect'); +Database.setCorruptionLogger = setCorruptionLogger; module.exports = Database; setErrorConstructor(require('./sqlite-error')); diff --git a/src/better_sqlite3.cpp b/src/better_sqlite3.cpp index c1d1e45d..138adaff 100644 --- a/src/better_sqlite3.cpp +++ b/src/better_sqlite3.cpp @@ -18,6 +18,7 @@ NODE_MODULE_INIT(/* exports, context */) { exports->Set(context, InternalizedFromLatin1(isolate, "StatementIterator"), StatementIterator::Init(isolate, data)).FromJust(); exports->Set(context, InternalizedFromLatin1(isolate, "Backup"), Backup::Init(isolate, data)).FromJust(); exports->Set(context, InternalizedFromLatin1(isolate, "setErrorConstructor"), v8::FunctionTemplate::New(isolate, Addon::JS_setErrorConstructor, data)->GetFunction(context).ToLocalChecked()).FromJust(); + exports->Set(context, InternalizedFromLatin1(isolate, "setCorruptionLogger"), v8::FunctionTemplate::New(isolate, Addon::JS_setCorruptionLogger, data)->GetFunction(context).ToLocalChecked()).FromJust(); // Store addon instance data. addon->Statement.Reset(isolate, v8::Local::Cast(exports->Get(context, InternalizedFromLatin1(isolate, "Statement")).ToLocalChecked())); @@ -1669,6 +1670,48 @@ void Addon::JS_setErrorConstructor (v8::FunctionCallbackInfo const if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > SqliteError = v8 :: Local < v8 :: Function > :: Cast ( info [ 0 ] ) ; static_cast < Addon * > ( v8 :: Local < v8 :: External > :: Cast ( info . Data ( ) ) -> Value ( ) ) ->SqliteError.Reset( info . GetIsolate ( ) , SqliteError); } + +class LogWrapper { + public: + LogWrapper( + v8::Isolate* isolate, + v8::Local fn + ): isolate_(isolate) { + fn_.Reset(isolate, fn); + } + + void Call(const char* msg) { + v8::HandleScope scope(isolate_); + v8::Local fn = + v8::Local::New(isolate_, fn_); + v8::Local arg = StringFromUtf8(isolate_, msg, -1); + fn->Call(isolate_->GetCurrentContext(), v8::Undefined(isolate_), 1, &arg); + } + + static void Fn(void *pArg, int iErrCode, const char *zMsg) { + LogWrapper* wrapper = reinterpret_cast(pArg); + if (iErrCode == SQLITE_CORRUPT || iErrCode == SQLITE_NOTADB) { + wrapper->Call(zMsg); + } + } + + private: + v8::Isolate* isolate_; + v8::Persistent fn_; +}; + +void Addon::JS_setCorruptionLogger (v8::FunctionCallbackInfo const & info) { + if (info.Length() <= 0) + return ThrowTypeError("Expected one argument"); + + v8::Local fn = v8::Local::Cast(info[0]); + int status = sqlite3_config( + SQLITE_CONFIG_LOG, + LogWrapper::Fn, + new LogWrapper(v8::Isolate::GetCurrent(), fn)); + assert(status == SQLITE_OK); +} + #line 48 "./src/better_sqlite3.lzz" void Addon::Cleanup (void * ptr) #line 48 "./src/better_sqlite3.lzz" diff --git a/src/better_sqlite3.hpp b/src/better_sqlite3.hpp index 37bf6699..54468c9c 100644 --- a/src/better_sqlite3.hpp +++ b/src/better_sqlite3.hpp @@ -665,6 +665,7 @@ struct Addon std::set dbs; #line 43 "./src/better_sqlite3.lzz" static void JS_setErrorConstructor (v8::FunctionCallbackInfo const & info); + static void JS_setCorruptionLogger (v8::FunctionCallbackInfo const & info); #line 48 "./src/better_sqlite3.lzz" static void Cleanup (void * ptr); #line 55 "./src/better_sqlite3.lzz"