diff --git a/src/async.h b/src/async.h index b1a8f9dd6..f36e4cbc2 100644 --- a/src/async.h +++ b/src/async.h @@ -29,20 +29,19 @@ template class Async { } static void listener(uv_async_t* handle) { - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); std::vector rows; NODE_SQLITE3_MUTEX_LOCK(&async->mutex) rows.swap(async->data); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) - for (unsigned int i = 0, size = rows.size(); i < size; i++) { - async->callback(async->parent, rows[i]); - } + for(auto row : rows) + async->callback(async->parent, row); } static void close(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } @@ -56,7 +55,7 @@ template class Async { void add(Item* item) { NODE_SQLITE3_MUTEX_LOCK(&mutex); - data.push_back(item); + data.emplace_back(item); NODE_SQLITE3_MUTEX_UNLOCK(&mutex) } diff --git a/src/backup.cc b/src/backup.cc index 9f3893b96..50adba6af 100644 --- a/src/backup.cc +++ b/src/backup.cc @@ -1,6 +1,5 @@ -#include +#include #include - #include "macros.h" #include "database.h" #include "backup.h" @@ -11,9 +10,9 @@ Napi::Object Backup::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Backup", { + auto t = DefineClass(env, "Backup", { InstanceMethod("step", &Backup::Step, napi_default_method), InstanceMethod("finish", &Backup::Finish, napi_default_method), InstanceAccessor("idle", &Backup::IdleGetter, nullptr), @@ -34,7 +33,7 @@ void Backup::Process() { } while (inited && !locked && !queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); call->callback(call->baton); @@ -43,11 +42,11 @@ void Backup::Process() { void Backup::Schedule(Work_Callback callback, Baton* baton) { if (finished) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); CleanQueue(); } else if (!inited || locked || !queue.empty()) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); } else { callback(baton); @@ -55,7 +54,7 @@ void Backup::Schedule(Work_Callback callback, Baton* baton) { } template void Backup::Error(T* baton) { - Napi::Env env = baton->backup->Env(); + auto env = baton->backup->Env(); Napi::HandleScope scope(env); Backup* backup = baton->backup; @@ -76,7 +75,7 @@ template void Backup::Error(T* baton) { } void Backup::CleanQueue() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (inited && !queue.empty()) { @@ -88,7 +87,7 @@ void Backup::CleanQueue() { // Clear out the queue so that this object can get GC'ed. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); std::unique_ptr baton(call->baton); @@ -111,7 +110,7 @@ void Backup::CleanQueue() { else while (!queue.empty()) { // Just delete all items in the queue; we already fired an event when // initializing the backup failed. - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); // We don't call the actual callback, so we have to make sure that @@ -121,13 +120,13 @@ void Backup::CleanQueue() { } Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - Napi::Env env = info.Env(); + auto env = info.Env(); if (!info.IsConstructCall()) { Napi::TypeError::New(env, "Use the new operator to create new Backup objects").ThrowAsJavaScriptException(); return; } - int length = info.Length(); + auto length = info.Length(); if (length <= 0 || !Database::HasInstance(info[0])) { Napi::TypeError::New(env, "Database object expected").ThrowAsJavaScriptException(); @@ -154,32 +153,32 @@ Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) return; } - Database* db = Napi::ObjectWrap::Unwrap(info[0].As()); - Napi::String filename = info[1].As(); - Napi::String sourceName = info[2].As(); - Napi::String destName = info[3].As(); - Napi::Boolean filenameIsDest = info[4].As(); + auto* database = Napi::ObjectWrap::Unwrap(info[0].As()); + auto filename = info[1].As(); + auto sourceName = info[2].As(); + auto destName = info[3].As(); + auto filenameIsDest = info[4].As(); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filename", filename)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sourceName", sourceName)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("destName", destName)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filenameIsDest", filenameIsDest)); - init(db); + init(database); - InitializeBaton* baton = new InitializeBaton(db, info[5].As(), this); + auto* baton = new InitializeBaton(database, info[5].As(), this); baton->filename = filename.Utf8Value(); baton->sourceName = sourceName.Utf8Value(); baton->destName = destName.Utf8Value(); baton->filenameIsDest = filenameIsDest.Value(); - db->Schedule(Work_BeginInitialize, baton); + database->Schedule(Work_BeginInitialize, baton); } void Backup::Work_BeginInitialize(Database::Baton* baton) { assert(baton->db->open); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( + auto env = baton->db->Env(); + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Backup.Initialize"), Work_Initialize, Work_AfterInitialize, baton, &baton->request ); @@ -192,7 +191,7 @@ void Backup::Work_Initialize(napi_env e, void* data) { // In case stepping fails, we use a mutex to make sure we get the associated // error message. - sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle); + auto* mtx = sqlite3_db_mutex(baton->db->_handle); sqlite3_mutex_enter(mtx); backup->status = sqlite3_open(baton->filename.c_str(), &backup->_otherDb); @@ -218,9 +217,9 @@ void Backup::Work_Initialize(napi_env e, void* data) { void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); if (backup->status != SQLITE_OK) { @@ -239,13 +238,13 @@ void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) { } Napi::Value Backup::Step(const Napi::CallbackInfo& info) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); REQUIRE_ARGUMENT_INTEGER(0, pages); OPTIONAL_ARGUMENT_FUNCTION(1, callback); - StepBaton* baton = new StepBaton(backup, callback, pages); + auto* baton = new StepBaton(backup, callback, pages); backup->GetRetryErrors(baton->retryErrorsSet); backup->Schedule(Work_BeginStep, baton); return info.This(); @@ -281,9 +280,9 @@ void Backup::Work_Step(napi_env e, void* data) { void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); if (backup->status == SQLITE_DONE) { @@ -308,12 +307,12 @@ void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) { } Napi::Value Backup::Finish(const Napi::CallbackInfo& info) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(backup, callback); + auto* baton = new Baton(backup, callback); backup->Schedule(Work_BeginFinish, baton); return info.This(); } @@ -329,9 +328,9 @@ void Backup::Work_Finish(napi_env e, void* data) { void Backup::Work_AfterFinish(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); backup->FinishAll(); @@ -369,39 +368,39 @@ void Backup::FinishSqlite() { } Napi::Value Backup::IdleGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; bool idle = backup->inited && !backup->locked && backup->queue.empty(); return Napi::Boolean::New(this->Env(), idle); } Napi::Value Backup::CompletedGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Boolean::New(this->Env(), backup->completed); } Napi::Value Backup::FailedGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Boolean::New(this->Env(), backup->failed); } Napi::Value Backup::RemainingGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Number::New(this->Env(), backup->remaining); } Napi::Value Backup::PageCountGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Number::New(this->Env(), backup->pageCount); } Napi::Value Backup::RetryErrorGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return backup->retryErrors.Value(); } void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); if (!value.IsArray()) { Napi::Error::New(env, "retryErrors must be an array").ThrowAsJavaScriptException(); return; @@ -413,9 +412,9 @@ void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& void Backup::GetRetryErrors(std::set& retryErrorsSet) { retryErrorsSet.clear(); Napi::Array array = retryErrors.Value(); - int length = array.Length(); - for (int i = 0; i < length; i++) { - Napi::Value code = (array).Get(i); + auto length = array.Length(); + for (size_t i = 0; i < length; i++) { + Napi::Value code = (array).Get(static_cast(i)); if (code.IsNumber()) { retryErrorsSet.insert(code.As().Int32Value()); } diff --git a/src/backup.h b/src/backup.h index c15b77bfe..2ce8e9048 100644 --- a/src/backup.h +++ b/src/backup.h @@ -121,7 +121,7 @@ class Backup : public Napi::ObjectWrap { Baton(db_, cb_), backup(backup_), filenameIsDest(true) { backup->Ref(); } - virtual ~InitializeBaton() { + virtual ~InitializeBaton() override { backup->Unref(); if (!db->IsOpen() && db->IsLocked()) { // The database handle was closed before the backup could be opened. @@ -135,6 +135,7 @@ class Backup : public Napi::ObjectWrap { std::set retryErrorsSet; StepBaton(Backup* backup_, Napi::Function cb_, int pages_) : Baton(backup_, cb_), pages(pages_) {} + virtual ~StepBaton() override = default; }; typedef void (*Work_Callback)(Baton* baton); @@ -169,8 +170,8 @@ class Backup : public Napi::ObjectWrap { retryErrors.Reset(); } - WORK_DEFINITION(Step); - WORK_DEFINITION(Finish); + WORK_DEFINITION(Step) + WORK_DEFINITION(Finish) Napi::Value IdleGetter(const Napi::CallbackInfo& info); Napi::Value CompletedGetter(const Napi::CallbackInfo& info); Napi::Value FailedGetter(const Napi::CallbackInfo& info); @@ -211,7 +212,7 @@ class Backup : public Napi::ObjectWrap { int remaining; int pageCount; bool finished; - std::queue queue; + std::queue> queue; Napi::Reference retryErrors; }; diff --git a/src/database.cc b/src/database.cc index 15709ce3d..77d8f7074 100644 --- a/src/database.cc +++ b/src/database.cc @@ -1,4 +1,4 @@ -#include +#include #include #include "macros.h" @@ -14,9 +14,9 @@ Napi::FunctionReference Database::constructor; Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Database", { + auto t = DefineClass(env, "Database", { InstanceMethod("close", &Database::Close, napi_default_method), InstanceMethod("exec", &Database::Exec, napi_default_method), InstanceMethod("wait", &Database::Wait, napi_default_method), @@ -42,7 +42,7 @@ Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { } void Database::Process() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (!open && locked && !queue.empty()) { @@ -52,9 +52,9 @@ void Database::Process() { // Call all callbacks with the error object. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); - std::unique_ptr baton(call->baton); + auto baton = std::unique_ptr(call->baton); Napi::Function cb = baton->callback.Value(); if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(this->Value(), cb, 1, argv); @@ -88,7 +88,7 @@ void Database::Process() { } void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (!open && locked) { @@ -109,7 +109,7 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { } if (!open || ((locked || exclusive || serialize) && pending > 0)) { - queue.push(new Call(callback, baton, exclusive || serialize)); + queue.emplace(new Call(callback, baton, exclusive || serialize)); } else { locked = exclusive; @@ -119,13 +119,13 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { Database::Database(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { init(); - Napi::Env env = info.Env(); + auto env = info.Env(); if (info.Length() <= 0 || !info[0].IsString()) { Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException(); return; } - std::string filename = info[0].As(); + auto filename = info[0].As().Utf8Value(); unsigned int pos = 1; @@ -146,13 +146,13 @@ Database::Database(const Napi::CallbackInfo& info) : Napi::ObjectWrap( info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("mode", Napi::Number::New(env, mode), napi_default)); // Start opening the database. - OpenBaton* baton = new OpenBaton(this, callback, filename.c_str(), mode); + auto* baton = new OpenBaton(this, callback, filename.c_str(), mode); Work_BeginOpen(baton); } void Database::Work_BeginOpen(Baton* baton) { - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( + auto env = baton->db->Env(); + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Database.Open"), Work_Open, Work_AfterOpen, baton, &baton->request ); @@ -161,8 +161,8 @@ void Database::Work_BeginOpen(Baton* baton) { } void Database::Work_Open(napi_env e, void* data) { - OpenBaton* baton = static_cast(data); - Database* db = baton->db; + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_open_v2( baton->filename.c_str(), @@ -185,9 +185,9 @@ void Database::Work_Open(napi_env e, void* data) { void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[1]; @@ -218,17 +218,17 @@ void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { } Napi::Value Database::OpenGetter(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; return Napi::Boolean::New(env, db->open); } Napi::Value Database::Close(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - Database* db = this; + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_BeginClose, baton, true); return info.This(); @@ -244,9 +244,9 @@ void Database::Work_BeginClose(Baton* baton) { baton->db->RemoveCallbacks(); baton->db->closing = true; - Napi::Env env = baton->db->Env(); + auto env = baton->db->Env(); - int status = napi_create_async_work( + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Database.Close"), Work_Close, Work_AfterClose, baton, &baton->request ); @@ -255,8 +255,8 @@ void Database::Work_BeginClose(Baton* baton) { } void Database::Work_Close(napi_env e, void* data) { - Baton* baton = static_cast(data); - Database* db = baton->db; + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_close(db->_handle); @@ -271,9 +271,9 @@ void Database::Work_Close(napi_env e, void* data) { void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); db->pending--; @@ -310,8 +310,8 @@ void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { } Napi::Value Database::Serialize(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); bool before = db->serialize; @@ -328,11 +328,11 @@ Napi::Value Database::Serialize(const Napi::CallbackInfo& info) { } Napi::Value Database::Parallelize(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - bool before = db->serialize; + auto before = db->serialize; db->serialize = false; if (!callback.IsEmpty() && callback.IsFunction()) { @@ -346,19 +346,18 @@ Napi::Value Database::Parallelize(const Napi::CallbackInfo& info) { } Napi::Value Database::Configure(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENTS(2); - if (info[0].StrictEquals( Napi::String::New(env, "trace"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + Napi::Function handle; + if (info[0].StrictEquals( Napi::String::New(env, "trace"))) { + auto* baton = new Baton(db, handle); db->Schedule(RegisterTraceCallback, baton); } else if (info[0].StrictEquals( Napi::String::New(env, "profile"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); db->Schedule(RegisterProfileCallback, baton); } else if (info[0].StrictEquals( Napi::String::New(env, "busyTimeout"))) { @@ -366,8 +365,7 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { Napi::TypeError::New(env, "Value must be an integer").ThrowAsJavaScriptException(); return env.Null(); } - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); baton->status = info[1].As().Int32Value(); db->Schedule(SetBusyTimeout, baton); } @@ -381,15 +379,13 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { Napi::TypeError::New(env, "limit value must be an integer").ThrowAsJavaScriptException(); return env.Null(); } - Napi::Function handle; int id = info[1].As().Int32Value(); int value = info[2].As().Int32Value(); Baton* baton = new LimitBaton(db, handle, id, value); db->Schedule(SetLimit, baton); } else if (info[0].StrictEquals(Napi::String::New(env, "change"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); db->Schedule(RegisterUpdateCallback, baton); } else { @@ -409,8 +405,8 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { } Napi::Value Database::Interrupt(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; if (!db->open) { Napi::Error::New(env, "Database is not open").ThrowAsJavaScriptException(); @@ -427,7 +423,7 @@ Napi::Value Database::Interrupt(const Napi::CallbackInfo& info) { } void Database::SetBusyTimeout(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); @@ -446,10 +442,10 @@ void Database::SetLimit(Baton* b) { } void Database::RegisterTraceCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_trace == NULL) { // Add it. @@ -473,7 +469,7 @@ void Database::TraceCallback(void* db, const char* sql) { void Database::TraceCallback(Database* db, std::string* s) { std::unique_ptr sql(s); // Note: This function is called in the main V8 thread. - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -484,10 +480,10 @@ void Database::TraceCallback(Database* db, std::string* s) { } void Database::RegisterProfileCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_profile == NULL) { // Add it. @@ -505,15 +501,15 @@ void Database::RegisterProfileCallback(Baton* b) { void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - ProfileInfo* info = new ProfileInfo(); + auto* info = new ProfileInfo(); info->sql = std::string(sql); info->nsecs = nsecs; static_cast(db)->debug_profile->send(info); } void Database::ProfileCallback(Database *db, ProfileInfo* i) { - std::unique_ptr info(i); - Napi::Env env = db->Env(); + auto info = std::unique_ptr(i); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -525,10 +521,10 @@ void Database::ProfileCallback(Database *db, ProfileInfo* i) { } void Database::RegisterUpdateCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->update_event == NULL) { // Add it. @@ -547,7 +543,7 @@ void Database::UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_int64 rowid) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - UpdateInfo* info = new UpdateInfo(); + auto* info = new UpdateInfo(); info->type = type; info->database = std::string(database); info->table = std::string(table); @@ -556,8 +552,8 @@ void Database::UpdateCallback(void* db, int type, const char* database, } void Database::UpdateCallback(Database *db, UpdateInfo* i) { - std::unique_ptr info(i); - Napi::Env env = db->Env(); + auto info = std::unique_ptr(i); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -571,8 +567,8 @@ void Database::UpdateCallback(Database *db, UpdateInfo* i) { } Napi::Value Database::Exec(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, sql); OPTIONAL_ARGUMENT_FUNCTION(1, callback); @@ -589,8 +585,8 @@ void Database::Work_BeginExec(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( + auto env = baton->db->Env(); + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Database.Exec"), Work_Exec, Work_AfterExec, baton, &baton->request ); @@ -599,7 +595,7 @@ void Database::Work_BeginExec(Baton* baton) { } void Database::Work_Exec(napi_env e, void* data) { - ExecBaton* baton = static_cast(data); + auto* baton = static_cast(data); char* message = NULL; baton->status = sqlite3_exec( @@ -619,10 +615,10 @@ void Database::Work_Exec(napi_env e, void* data) { void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; db->pending--; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Function cb = baton->callback.Value(); @@ -648,21 +644,21 @@ void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { } Napi::Value Database::Wait(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - Database* db = this; + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_Wait, baton, true); return info.This(); } void Database::Work_Wait(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); - Napi::Env env = baton->db->Env(); + auto env = baton->db->Env(); Napi::HandleScope scope(env); assert(baton->db->locked); @@ -680,8 +676,8 @@ void Database::Work_Wait(Baton* b) { } Napi::Value Database::LoadExtension(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, filename); OPTIONAL_ARGUMENT_FUNCTION(1, callback); @@ -698,8 +694,8 @@ void Database::Work_BeginLoadExtension(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( + auto env = baton->db->Env(); + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Database.LoadExtension"), Work_LoadExtension, Work_AfterLoadExtension, baton, &baton->request ); @@ -708,7 +704,7 @@ void Database::Work_BeginLoadExtension(Baton* baton) { } void Database::Work_LoadExtension(napi_env e, void* data) { - LoadExtensionBaton* baton = static_cast(data); + auto* baton = static_cast(data); sqlite3_enable_load_extension(baton->db->_handle, 1); @@ -731,10 +727,10 @@ void Database::Work_LoadExtension(napi_env e, void* data) { void Database::Work_AfterLoadExtension(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; db->pending--; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Function cb = baton->callback.Value(); diff --git a/src/database.h b/src/database.h index 420b5dd1c..4a79587ee 100644 --- a/src/database.h +++ b/src/database.h @@ -27,14 +27,14 @@ class Database : public Napi::ObjectWrap { static Napi::Object Init(Napi::Env env, Napi::Object exports); static inline bool HasInstance(Napi::Value val) { - Napi::Env env = val.Env(); + auto env = val.Env(); Napi::HandleScope scope(env); if (!val.IsObject()) return false; - Napi::Object obj = val.As(); + auto obj = val.As(); #if NAPI_VERSION < 6 return obj.InstanceOf(constructor.Value()); #else - Napi::FunctionReference* constructor = + auto constructor = env.GetInstanceData(); return obj.InstanceOf(constructor->Value()); #endif @@ -66,18 +66,21 @@ class Database : public Napi::ObjectWrap { int mode; OpenBaton(Database* db_, Napi::Function cb_, const char* filename_, int mode_) : Baton(db_, cb_), filename(filename_), mode(mode_) {} + virtual ~OpenBaton() override = default; }; struct ExecBaton : Baton { std::string sql; ExecBaton(Database* db_, Napi::Function cb_, const char* sql_) : Baton(db_, cb_), sql(sql_) {} + virtual ~ExecBaton() override = default; }; struct LoadExtensionBaton : Baton { std::string filename; LoadExtensionBaton(Database* db_, Napi::Function cb_, const char* filename_) : Baton(db_, cb_), filename(filename_) {} + virtual ~LoadExtensionBaton() override = default; }; struct LimitBaton : Baton { @@ -85,6 +88,7 @@ class Database : public Napi::ObjectWrap { int value; LimitBaton(Database* db_, Napi::Function cb_, int id_, int value_) : Baton(db_, cb_), id(id_), value(value_) {} + virtual ~LimitBaton() override = default; }; typedef void (*Work_Callback)(Baton* baton); diff --git a/src/macros.h b/src/macros.h index 344642d9d..8e4139d44 100644 --- a/src/macros.h +++ b/src/macros.h @@ -15,7 +15,7 @@ inline Napi::String StringConcat(Napi::Value str1, Napi::Value str2) { // A Napi substitute IsInt32() inline bool OtherIsInt(Napi::Number source) { double orig_val = source.DoubleValue(); - double int_val = (double)source.Int32Value(); + double int_val = static_cast(source.Int32Value()); if (orig_val == int_val) { return true; } else { @@ -23,6 +23,13 @@ inline bool OtherIsInt(Napi::Number source) { } } +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#else +# define UNUSED(x) x +#endif + #define IS_FUNCTION(cb) \ !cb.IsUndefined() && cb.IsFunction() @@ -145,8 +152,8 @@ inline bool OtherIsInt(Napi::Number source) { assert(baton->stmt->prepared); \ baton->stmt->locked = true; \ baton->stmt->db->pending++; \ - Napi::Env env = baton->stmt->Env(); \ - int status = napi_create_async_work( \ + auto env = baton->stmt->Env(); \ + int UNUSED(status) = napi_create_async_work( \ env, NULL, Napi::String::New(env, "sqlite3.Statement."#type), \ Work_##type, Work_After##type, baton, &baton->request \ ); \ @@ -181,8 +188,8 @@ inline bool OtherIsInt(Napi::Number source) { assert(baton->backup->inited); \ baton->backup->locked = true; \ baton->backup->db->pending++; \ - Napi::Env env = baton->backup->Env(); \ - int status = napi_create_async_work( \ + auto env = baton->backup->Env(); \ + int UNUSED(status) = napi_create_async_work( \ env, NULL, Napi::String::New(env, "sqlite3.Backup."#type), \ Work_##type, Work_After##type, baton, &baton->request \ ); \ @@ -201,15 +208,4 @@ inline bool OtherIsInt(Napi::Number source) { backup->Process(); \ backup->db->Process(); -#define DELETE_FIELD(field) \ - if (field != NULL) { \ - switch ((field)->type) { \ - case SQLITE_INTEGER: delete (Values::Integer*)(field); break; \ - case SQLITE_FLOAT: delete (Values::Float*)(field); break; \ - case SQLITE_TEXT: delete (Values::Text*)(field); break; \ - case SQLITE_BLOB: delete (Values::Blob*)(field); break; \ - case SQLITE_NULL: delete (Values::Null*)(field); break; \ - } \ - } - -#endif +#endif \ No newline at end of file diff --git a/src/statement.cc b/src/statement.cc index 29e06f992..c5653fa07 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -12,9 +12,9 @@ Napi::Object Statement::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Statement", { + auto t = DefineClass(env, "Statement", { InstanceMethod("bind", &Statement::Bind, napi_default_method), InstanceMethod("get", &Statement::Get, napi_default_method), InstanceMethod("run", &Statement::Run, napi_default_method), @@ -45,7 +45,7 @@ void Statement::Process() { } while (prepared && !locked && !queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); call->callback(call->baton); @@ -54,11 +54,11 @@ void Statement::Process() { void Statement::Schedule(Work_Callback callback, Baton* baton) { if (finalized) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); CleanQueue(); } else if (!prepared || locked) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); } else { callback(baton); @@ -68,7 +68,7 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) { template void Statement::Error(T* baton) { Statement* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); // Fail hard on logic errors. @@ -89,7 +89,7 @@ template void Statement::Error(T* baton) { // { Database db, String sql, Array params, Function callback } Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - Napi::Env env = info.Env(); + auto env = info.Env(); int length = info.Length(); if (length <= 0 || !Database::HasInstance(info[0])) { @@ -106,14 +106,14 @@ Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrap::Unwrap(info[0].As()); - Napi::String sql = info[1].As(); + auto sql = info[1].As(); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sql", sql, napi_default)); init(db); Statement* stmt = this; - PrepareBaton* baton = new PrepareBaton(db, info[2].As(), stmt); + auto* baton = new PrepareBaton(db, info[2].As(), stmt); baton->sql = std::string(sql.As().Utf8Value().c_str()); db->Schedule(Work_BeginPrepare, baton); } @@ -121,8 +121,8 @@ Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrapdb->open); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( + auto env = baton->db->Env(); + int UNUSED(status) = napi_create_async_work( env, NULL, Napi::String::New(env, "sqlite3.Statement.Prepare"), Work_Prepare, Work_AfterPrepare, baton, &baton->request ); @@ -156,9 +156,9 @@ void Statement::Work_Prepare(napi_env e, void* data) { void Statement::Work_AfterPrepare(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { @@ -177,45 +177,45 @@ void Statement::Work_AfterPrepare(napi_env e, napi_status status, void* data) { STATEMENT_END(); } -template Values::Field* +template std::unique_ptr Statement::BindParameter(const Napi::Value source, T pos) { if (source.IsString()) { std::string val = source.As().Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else if (OtherInstanceOf(source.As(), "RegExp")) { std::string val = source.ToString().Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else if (source.IsNumber()) { if (OtherIsInt(source.As())) { - return new Values::Integer(pos, source.As().Int32Value()); + return std::make_unique(pos, source.As().Int32Value()); } else { - return new Values::Float(pos, source.As().DoubleValue()); + return std::make_unique(pos, source.As().DoubleValue()); } } else if (source.IsBoolean()) { - return new Values::Integer(pos, source.As().Value() ? 1 : 0); + return std::make_unique(pos, source.As().Value() ? 1 : 0); } else if (source.IsNull()) { - return new Values::Null(pos); + return std::make_unique(pos); } else if (source.IsBuffer()) { Napi::Buffer buffer = source.As>(); - return new Values::Blob(pos, buffer.Length(), buffer.Data()); + return std::make_unique(pos, buffer.Length(), buffer.Data()); } else if (OtherInstanceOf(source.As(), "Date")) { - return new Values::Float(pos, source.ToNumber().DoubleValue()); + return std::make_unique(pos, source.ToNumber().DoubleValue()); } else if (source.IsObject()) { - Napi::String napiVal = Napi::String::New(source.Env(), "[object Object]"); + auto napiVal = Napi::String::New(source.Env(), "[object Object]"); // Check whether toString returned a value that is not undefined. if(napiVal.Type() == 0) { return NULL; } std::string val = napiVal.Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else { return NULL; @@ -223,7 +223,7 @@ template Values::Field* } template T* Statement::Bind(const Napi::CallbackInfo& info, int start, int last) { - Napi::Env env = info.Env(); + auto env = info.Env(); Napi::HandleScope scope(env); if (last < 0) last = info.Length(); @@ -233,38 +233,39 @@ template T* Statement::Bind(const Napi::CallbackInfo& info, int start, last--; } - T* baton = new T(this, callback); + auto *baton = new T(this, callback); if (start < last) { if (info[start].IsArray()) { - Napi::Array array = info[start].As(); + auto array = info[start].As(); int length = array.Length(); // Note: bind parameters start with 1. for (int i = 0, pos = 1; i < length; i++, pos++) { - baton->parameters.push_back(BindParameter((array).Get(i), pos)); + baton->parameters.emplace_back(BindParameter((array).Get(i), i + 1)); } } - else if (!info[start].IsObject() || OtherInstanceOf(info[start].As(), "RegExp") || OtherInstanceOf(info[start].As(), "Date") || info[start].IsBuffer()) { + else if (!info[start].IsObject() || OtherInstanceOf(info[start].As(), "RegExp") + || OtherInstanceOf(info[start].As(), "Date") || info[start].IsBuffer()) { // Parameters directly in array. // Note: bind parameters start with 1. for (int i = start, pos = 1; i < last; i++, pos++) { - baton->parameters.push_back(BindParameter(info[i], pos)); + baton->parameters.emplace_back(BindParameter(info[i], pos)); } } else if (info[start].IsObject()) { - Napi::Object object = info[start].As(); - Napi::Array array = object.GetPropertyNames(); + auto object = info[start].As(); + auto array = object.GetPropertyNames(); int length = array.Length(); for (int i = 0; i < length; i++) { Napi::Value name = (array).Get(i); Napi::Number num = name.ToNumber(); if (num.Int32Value() == num.DoubleValue()) { - baton->parameters.push_back( + baton->parameters.emplace_back( BindParameter((object).Get(name), num.Int32Value())); } else { - baton->parameters.push_back(BindParameter((object).Get(name), + baton->parameters.emplace_back(BindParameter((object).Get(name), name.As().Utf8Value().c_str())); } } @@ -278,67 +279,63 @@ template T* Statement::Bind(const Napi::CallbackInfo& info, int start, } bool Statement::Bind(const Parameters & parameters) { - if (parameters.size() == 0) { + if (parameters.empty()) { return true; } sqlite3_reset(_handle); sqlite3_clear_bindings(_handle); - Parameters::const_iterator it = parameters.begin(); - Parameters::const_iterator end = parameters.end(); - - for (; it < end; ++it) { - Values::Field* field = *it; + for (auto& field : parameters) { + if (field == NULL) + continue; - if (field != NULL) { - unsigned int pos; - if (field->index > 0) { - pos = field->index; - } - else { - pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); - } + unsigned int pos; + if (field->index > 0) { + pos = field->index; + } + else { + pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); + } - switch (field->type) { - case SQLITE_INTEGER: { - status = sqlite3_bind_int(_handle, pos, - ((Values::Integer*)field)->value); - } break; - case SQLITE_FLOAT: { - status = sqlite3_bind_double(_handle, pos, - ((Values::Float*)field)->value); - } break; - case SQLITE_TEXT: { - status = sqlite3_bind_text(_handle, pos, - ((Values::Text*)field)->value.c_str(), - ((Values::Text*)field)->value.size(), SQLITE_TRANSIENT); - } break; - case SQLITE_BLOB: { - status = sqlite3_bind_blob(_handle, pos, - ((Values::Blob*)field)->value, - ((Values::Blob*)field)->length, SQLITE_TRANSIENT); - } break; - case SQLITE_NULL: { - status = sqlite3_bind_null(_handle, pos); - } break; - } + switch (field->type) { + case SQLITE_INTEGER: { + status = sqlite3_bind_int(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_FLOAT: { + status = sqlite3_bind_double(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_TEXT: { + status = sqlite3_bind_text(_handle, pos, + (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size(), SQLITE_TRANSIENT); + } break; + case SQLITE_BLOB: { + status = sqlite3_bind_blob(_handle, pos, + (static_cast(field.get()))->value, + (static_cast(field.get()))->length, SQLITE_TRANSIENT); + } break; + case SQLITE_NULL: { + status = sqlite3_bind_null(_handle, pos); + } break; + } if (status != SQLITE_OK) { message = std::string(sqlite3_errmsg(db->_handle)); return false; } } - } return true; } Napi::Value Statement::Bind(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; - Baton* baton = stmt->Bind(info); + auto baton = stmt->Bind(info); if (baton == NULL) { Napi::TypeError::New(env, "Data type is not supported").ThrowAsJavaScriptException(); return env.Null(); @@ -364,9 +361,9 @@ void Statement::Work_Bind(napi_env e, void* data) { void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { @@ -387,7 +384,7 @@ void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { Napi::Value Statement::Get(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -431,9 +428,9 @@ void Statement::Work_Get(napi_env e, void* data) { void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -459,7 +456,7 @@ void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Run(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -505,9 +502,9 @@ void Statement::Work_Run(napi_env e, void* data) { void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -529,7 +526,7 @@ void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { } Napi::Value Statement::All(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -560,9 +557,9 @@ void Statement::Work_All(napi_env e, void* data) { if (stmt->Bind(baton->parameters)) { while ((stmt->status = sqlite3_step(stmt->_handle)) == SQLITE_ROW) { - Row* row = new Row(); - GetRow(row, stmt->_handle); - baton->rows.push_back(row); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); + baton->rows.emplace_back(std::move(row)); } if (stmt->status != SQLITE_DONE) { @@ -575,9 +572,9 @@ void Statement::Work_All(napi_env e, void* data) { void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { @@ -590,11 +587,10 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { if (baton->rows.size()) { // Create the result array from the data we acquired. Napi::Array result(Napi::Array::New(env, baton->rows.size())); - Rows::const_iterator it = baton->rows.begin(); - Rows::const_iterator end = baton->rows.end(); + auto it = static_cast(baton->rows.begin()); + decltype(it) end = baton->rows.end(); for (int i = 0; it < end; ++it, i++) { - std::unique_ptr row(*it); - (result).Set(i, RowToJS(env,row.get())); + (result).Set(i, RowToJS(env, it->get())); } Napi::Value argv[] = { env.Null(), result }; @@ -615,7 +611,7 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Each(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; int last = info.Length(); @@ -625,7 +621,7 @@ Napi::Value Statement::Each(const Napi::CallbackInfo& info) { completed = info[--last].As(); } - EachBaton* baton = stmt->Bind(info, 0, last); + auto baton = stmt->Bind(info, 0, last); if (baton == NULL) { Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); return env.Null(); @@ -640,7 +636,7 @@ Napi::Value Statement::Each(const Napi::CallbackInfo& info) { void Statement::Work_BeginEach(Baton* baton) { // Only create the Async object when we're actually going into // the event loop. This prevents dangling events. - EachBaton* each_baton = static_cast(baton); + auto* each_baton = static_cast(baton); each_baton->async = new Async(each_baton->stmt, reinterpret_cast(AsyncEach)); each_baton->async->item_cb.Reset(each_baton->callback.Value(), 1); each_baton->async->completed_cb.Reset(each_baton->completed.Value(), 1); @@ -651,7 +647,7 @@ void Statement::Work_BeginEach(Baton* baton) { void Statement::Work_Each(napi_env e, void* data) { STATEMENT_INIT(EachBaton); - Async* async = baton->async; + auto* async = baton->async; STATEMENT_MUTEX(mtx); @@ -668,10 +664,10 @@ void Statement::Work_Each(napi_env e, void* data) { stmt->status = sqlite3_step(stmt->_handle); if (stmt->status == SQLITE_ROW) { sqlite3_mutex_leave(mtx); - Row* row = new Row(); - GetRow(row, stmt->_handle); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); NODE_SQLITE3_MUTEX_LOCK(&async->mutex) - async->data.push_back(row); + async->data.emplace_back(std::move(row)); retrieved++; NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) @@ -694,14 +690,14 @@ void Statement::Work_Each(napi_env e, void* data) { void Statement::CloseCallback(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } void Statement::AsyncEach(uv_async_t* handle) { - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); - Napi::Env env = async->stmt->Env(); + auto env = async->stmt->Env(); Napi::HandleScope scope(env); while (true) { @@ -720,10 +716,7 @@ void Statement::AsyncEach(uv_async_t* handle) { Napi::Value argv[2]; argv[0] = env.Null(); - Rows::const_iterator it = rows.begin(); - Rows::const_iterator end = rows.end(); - for (int i = 0; it < end; ++it, i++) { - std::unique_ptr row(*it); + for(auto& row : rows) { argv[1] = RowToJS(env,row.get()); async->retrieved++; TRY_CATCH_CALL(async->stmt->Value(), cb, 2, argv); @@ -747,9 +740,9 @@ void Statement::AsyncEach(uv_async_t* handle) { void Statement::Work_AfterEach(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { @@ -760,12 +753,12 @@ void Statement::Work_AfterEach(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Reset(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); + auto* baton = new Baton(stmt, callback); stmt->Schedule(Work_BeginReset, baton); return info.This(); @@ -784,9 +777,9 @@ void Statement::Work_Reset(napi_env e, void* data) { void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); // Fire callbacks. @@ -802,27 +795,26 @@ void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { Napi::Value Statement::RowToJS(Napi::Env env, Row* row) { Napi::EscapableHandleScope scope(env); - Napi::Object result = Napi::Object::New(env); + auto result = Napi::Object::New(env); - Row::const_iterator it = row->begin(); - Row::const_iterator end = row->end(); - for (int i = 0; it < end; ++it, i++) { - Values::Field* field = *it; + for (auto& field : *row) { Napi::Value value; switch (field->type) { case SQLITE_INTEGER: { - value = Napi::Number::New(env, ((Values::Integer*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_FLOAT: { - value = Napi::Number::New(env, ((Values::Float*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_TEXT: { - value = Napi::String::New(env, ((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()); + value = Napi::String::New(env, (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size()); } break; case SQLITE_BLOB: { - value = Napi::Buffer::Copy(env, ((Values::Blob*)field)->value, ((Values::Blob*)field)->length); + value = Napi::Buffer::Copy(env, (static_cast(field.get()))->value, + (static_cast(field.get()))->length); } break; case SQLITE_NULL: { value = env.Null(); @@ -830,8 +822,6 @@ Napi::Value Statement::RowToJS(Napi::Env env, Row* row) { } (result).Set(Napi::String::New(env, field->name.c_str()), value); - - DELETE_FIELD(field); } return scope.Escape(result); @@ -849,23 +839,23 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { switch (type) { case SQLITE_INTEGER: { - row->push_back(new Values::Integer(name, sqlite3_column_int64(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_int64(stmt, i))); } break; case SQLITE_FLOAT: { - row->push_back(new Values::Float(name, sqlite3_column_double(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_double(stmt, i))); } break; case SQLITE_TEXT: { const char* text = (const char*)sqlite3_column_text(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Text(name, length, text)); + row->emplace_back(std::make_unique(name, length, text)); } break; case SQLITE_BLOB: { const void* blob = sqlite3_column_blob(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Blob(name, length, blob)); + row->emplace_back(std::make_unique(name, length, blob)); } break; case SQLITE_NULL: { - row->push_back(new Values::Null(name)); + row->emplace_back(std::make_unique(name)); } break; default: assert(false); @@ -874,19 +864,19 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { } Napi::Value Statement::Finalize_(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); + auto *baton = new Baton(stmt, callback); stmt->Schedule(Finalize_, baton); return stmt->db->Value(); } void Statement::Finalize_(Baton* b) { - std::unique_ptr baton(b); - Napi::Env env = baton->stmt->Env(); + auto baton = std::unique_ptr(b); + auto env = baton->stmt->Env(); Napi::HandleScope scope(env); baton->stmt->Finalize_(); @@ -910,7 +900,7 @@ void Statement::Finalize_() { } void Statement::CleanQueue() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (prepared && !queue.empty()) { @@ -922,10 +912,10 @@ void Statement::CleanQueue() { // Clear out the queue so that this object can get GC'ed. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); - std::unique_ptr baton(call->baton); + auto baton = std::unique_ptr(call->baton); Napi::Function cb = baton->callback.Value(); if (prepared && !cb.IsEmpty() && @@ -945,7 +935,7 @@ void Statement::CleanQueue() { else while (!queue.empty()) { // Just delete all items in the queue; we already fired an event when // preparing the statement failed. - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); // We don't call the actual callback, so we have to make sure that // the baton gets destroyed. diff --git a/src/statement.h b/src/statement.h index dec0015d1..397593e33 100644 --- a/src/statement.h +++ b/src/statement.h @@ -6,7 +6,6 @@ #include #include #include - #include #include #include @@ -28,34 +27,40 @@ namespace Values { unsigned short type; unsigned short index; std::string name; + + virtual ~Field() = default; }; struct Integer : Field { template inline Integer(T _name, int64_t val) : Field(_name, SQLITE_INTEGER), value(val) {} int64_t value; + virtual ~Integer() override = default; }; struct Float : Field { template inline Float(T _name, double val) : Field(_name, SQLITE_FLOAT), value(val) {} double value; + virtual ~Float() override = default; }; struct Text : Field { template inline Text(T _name, size_t len, const char* val) : Field(_name, SQLITE_TEXT), value(val, len) {} std::string value; + virtual ~Text() override = default; }; struct Blob : Field { template inline Blob(T _name, size_t len, const void* val) : Field(_name, SQLITE_BLOB), length(len) { - value = (char*)malloc(len); + value = new char[len]; + assert(value != nullptr); memcpy(value, val, len); } - inline ~Blob() { - free(value); + inline virtual ~Blob() override { + delete[] value; } int length; char* value; @@ -64,8 +69,8 @@ namespace Values { typedef Field Null; } -typedef std::vector Row; -typedef std::vector Rows; +typedef std::vector> Row; +typedef std::vector> Rows; typedef Row Parameters; @@ -86,10 +91,7 @@ class Statement : public Napi::ObjectWrap { callback.Reset(cb_, 1); } virtual ~Baton() { - for (size_t i = 0; i < parameters.size(); i++) { - Values::Field* field = parameters[i]; - DELETE_FIELD(field); - } + parameters.clear(); if (request) napi_delete_async_work(stmt->Env(), request); stmt->Unref(); callback.Reset(); @@ -100,6 +102,7 @@ class Statement : public Napi::ObjectWrap { RowBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Row row; + virtual ~RowBaton() override = default; }; struct RunBaton : Baton { @@ -107,12 +110,14 @@ class Statement : public Napi::ObjectWrap { Baton(stmt_, cb_), inserted_id(0), changes(0) {} sqlite3_int64 inserted_id; int changes; + virtual ~RunBaton() override = default; }; struct RowsBaton : Baton { RowsBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Rows rows; + virtual ~RowsBaton() override = default; }; struct Async; @@ -123,7 +128,7 @@ class Statement : public Napi::ObjectWrap { EachBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} - virtual ~EachBaton() { + virtual ~EachBaton() override { completed.Reset(); } }; @@ -135,7 +140,7 @@ class Statement : public Napi::ObjectWrap { Baton(db_, cb_), stmt(stmt_) { stmt->Ref(); } - virtual ~PrepareBaton() { + virtual ~PrepareBaton() override { stmt->Unref(); if (!db->IsOpen() && db->IsLocked()) { // The database handle was closed before the statement could be @@ -200,12 +205,12 @@ class Statement : public Napi::ObjectWrap { if (!finalized) Finalize_(); } - WORK_DEFINITION(Bind); - WORK_DEFINITION(Get); - WORK_DEFINITION(Run); - WORK_DEFINITION(All); - WORK_DEFINITION(Each); - WORK_DEFINITION(Reset); + WORK_DEFINITION(Bind) + WORK_DEFINITION(Get) + WORK_DEFINITION(Run) + WORK_DEFINITION(All) + WORK_DEFINITION(Each) + WORK_DEFINITION(Reset) Napi::Value Finalize_(const Napi::CallbackInfo& info); @@ -220,7 +225,7 @@ class Statement : public Napi::ObjectWrap { static void Finalize_(Baton* baton); void Finalize_(); - template inline Values::Field* BindParameter(const Napi::Value source, T pos); + template inline std::unique_ptr BindParameter(const Napi::Value source, T pos); template T* Bind(const Napi::CallbackInfo& info, int start = 0, int end = -1); bool Bind(const Parameters ¶meters); diff --git a/test/support/createdb.js b/test/support/createdb.js index 3c7308ed8..ee22d05e8 100755 --- a/test/support/createdb.js +++ b/test/support/createdb.js @@ -2,6 +2,7 @@ function createdb(callback) { var existsSync = require('fs').existsSync || require('path').existsSync; + var statSync = require('fs').statSync || require('path').statSync; var path = require('path'); var sqlite3 = require('../../lib/sqlite3'); @@ -18,8 +19,8 @@ function createdb(callback) { return str; } - - if (existsSync(db_path)) { +// Make sure the file exists and is also valid. + if (existsSync(db_path) && statSync(db_path).size !== 0) { console.log('okay: database already created (' + db_path + ')'); if (callback) callback(); } else {