Skip to content

Commit

Permalink
fix sqlite JS engine state problem
Browse files Browse the repository at this point in the history
fixes #450
  • Loading branch information
obastemur committed Jul 17, 2015
1 parent d4420d8 commit a6f0ac6
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 44 deletions.
2 changes: 1 addition & 1 deletion lib/external/sqlite3.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function extendTrace(object, property, pos) {
+ Array.prototype.slice.call(arguments).map(function(el) {
return util.inspect(el, false, 0);
}).join(', ') + ')';

if (typeof pos === 'undefined')
pos = -1;
if (pos < 0)
Expand Down
Empty file modified src/external/sqlite3/async.h
100644 → 100755
Empty file.
54 changes: 30 additions & 24 deletions src/external/sqlite3/database.cc
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ using namespace node;
jxcore::ThreadStore<JS_PERSISTENT_FUNCTION_TEMPLATE> Database::jx_persistent;

void Database::Process() {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

if (!open && locked && !queue.empty()) {
node::commons* com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);

EXCEPTION("Database handle is closed", SQLITE_MISUSE, exception);
JS_LOCAL_VALUE argv[] = {exception};
bool called = false;
Expand All @@ -24,7 +24,8 @@ void Database::Process() {
Call* call = queue.front();
if (!JS_IS_EMPTY(call->baton->callback) &&
JS_IS_FUNCTION(call->baton->callback)) {
TRY_CATCH_CALL(handle_, JS_TYPE_TO_LOCAL_FUNCTION(call->baton->callback), 1, argv);
TRY_CATCH_CALL(
handle_, JS_TYPE_TO_LOCAL_FUNCTION(call->baton->callback), 1, argv);
called = true;
}
queue.pop();
Expand Down Expand Up @@ -61,12 +62,13 @@ void Database::Process() {

void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) {
if (!open && locked) {
node::commons *com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);
node::commons* com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);
EXCEPTION("Database is closed", SQLITE_MISUSE, exception);
if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {exception};
TRY_CATCH_CALL(handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
} else {
JS_LOCAL_VALUE argv[] = {STD_TO_STRING("error"), exception};
EMIT_EVENT(handle_, 2, argv);
Expand Down Expand Up @@ -143,7 +145,6 @@ void Database::Work_Open(uv_work_t* req) {
void Database::Work_AfterOpen(uv_work_t* req) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

OpenBaton* baton = static_cast<OpenBaton*>(req->data);
Database* db = baton->db;

Expand All @@ -157,7 +158,8 @@ void Database::Work_AfterOpen(uv_work_t* req) {
}

if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
} else if (!db->open) {
JS_LOCAL_VALUE args[] = {STD_TO_STRING("error"), argv[0]};
EMIT_EVENT(db->handle_, 2, args);
Expand Down Expand Up @@ -228,7 +230,8 @@ void Database::Work_AfterClose(uv_work_t* req) {

// Fire callbacks.
if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
} else if (db->open) {
JS_LOCAL_VALUE args[] = {STD_TO_STRING("error"), argv[0]};
EMIT_EVENT(db->handle_, 2, args);
Expand All @@ -251,8 +254,8 @@ JS_METHOD(Database, Serialize) {
db->serialize = true;

if (!JS_IS_EMPTY(callback) && JS_IS_FUNCTION(callback)) {
JS_HANDLE_OBJECT _this = args.This();
TRY_CATCH_CALL_NO_PARAM(_this, JS_TYPE_TO_LOCAL_FUNCTION(callback));
JS_HANDLE_OBJECT _this = args.This();
TRY_CATCH_CALL_NO_PARAM(_this, JS_TYPE_TO_LOCAL_FUNCTION(callback));
db->serialize = before;
}

Expand All @@ -270,8 +273,8 @@ JS_METHOD(Database, Parallelize) {
db->serialize = false;

if (!JS_IS_EMPTY(callback) && JS_IS_FUNCTION(callback)) {
JS_HANDLE_OBJECT _this = args.This();
TRY_CATCH_CALL_NO_PARAM(_this, JS_TYPE_TO_LOCAL_FUNCTION(callback));
JS_HANDLE_OBJECT _this = args.This();
TRY_CATCH_CALL_NO_PARAM(_this, JS_TYPE_TO_LOCAL_FUNCTION(callback));
db->serialize = before;
}

Expand Down Expand Up @@ -440,7 +443,7 @@ void Database::UpdateCallback(Database* db, UpdateInfo* info) {
JS_LOCAL_VALUE argv[] = {STD_TO_STRING(sqlite_authorizer_string(info->type)),
STD_TO_STRING(info->database.c_str()),
STD_TO_STRING(info->table.c_str()),
STD_TO_INTEGER(info->rowid), };
STD_TO_INTEGER(info->rowid)};
EMIT_EVENT(db->handle_, 4, argv);
delete info;
}
Expand Down Expand Up @@ -493,15 +496,16 @@ void Database::Work_AfterExec(uv_work_t* req) {

if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {exception};
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
} else {
JS_LOCAL_VALUE args[] = {STD_TO_STRING("error"), exception};
EMIT_EVENT(db->handle_, 2, args);
}
} else if (!JS_IS_EMPTY(baton->callback) &&
JS_IS_FUNCTION(baton->callback)) {
} else if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {JS_NULL()};
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
}

db->Process();
Expand Down Expand Up @@ -532,7 +536,8 @@ void Database::Work_Wait(Baton* baton) {

if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {JS_NULL()};
TRY_CATCH_CALL(baton->db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(baton->db->handle_,
JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
}

baton->db->Process();
Expand Down Expand Up @@ -593,15 +598,16 @@ void Database::Work_AfterLoadExtension(uv_work_t* req) {

if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {exception};
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
} else {
JS_LOCAL_VALUE args[] = {STD_TO_STRING("error"), exception};
EMIT_EVENT(db->handle_, 2, args);
}
} else if (!JS_IS_EMPTY(baton->callback) &&
JS_IS_FUNCTION(baton->callback)) {
} else if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
JS_LOCAL_VALUE argv[] = {JS_NULL()};
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1, argv);
TRY_CATCH_CALL(db->handle_, JS_TYPE_TO_LOCAL_FUNCTION(baton->callback), 1,
argv);
}

db->Process();
Expand Down
5 changes: 3 additions & 2 deletions src/external/sqlite3/database.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ class Database : public ObjectWrap {

INIT_NAMED_CLASS_MEMBERS(Database, Database) {
int id = com->threadId;
jx_persistent.templates[id] =
JS_NEW_PERSISTENT_FUNCTION_TEMPLATE(constructor);

SET_INSTANCE_METHOD("close", Close, 0);
SET_INSTANCE_METHOD("exec", Exec, 0);
Expand All @@ -44,6 +42,9 @@ class Database : public ObjectWrap {
#elif defined(JS_ENGINE_MOZJS)
JS_ACCESSOR_SET(constructor, STD_TO_STRING("open"), OpenGetter, NULL);
#endif

jx_persistent.templates[id] =
JS_NEW_PERSISTENT_FUNCTION_TEMPLATE(constructor);
}
END_INIT_NAMED_MEMBERS(Database)

Expand Down
Empty file modified src/external/sqlite3/macros.h
100644 → 100755
Empty file.
Empty file modified src/external/sqlite3/node_sqlite3.cc
100644 → 100755
Empty file.
35 changes: 18 additions & 17 deletions src/external/sqlite3/statement.cc
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) {

template <class T>
void Statement::Error(T* baton) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);
Statement* stmt = baton->stmt;
// Fail hard on logic errors.
assert(stmt->status != 0);
node::commons* com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);
EXCEPTION(stmt->message.c_str(), stmt->status, exception);

if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
Expand All @@ -56,7 +56,6 @@ void Statement::Error(T* baton) {
}
}

// { Database db, String sql, Array params, Function callback }
JS_METHOD(Statement, New) {
if (!args.IsConstructCall()) {
THROW_TYPE_EXCEPTION(
Expand Down Expand Up @@ -122,7 +121,6 @@ void Statement::Work_Prepare(uv_work_t* req) {
void Statement::Work_AfterPrepare(uv_work_t* req) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

STATEMENT_INIT(PrepareBaton);

if (stmt->status != SQLITE_OK) {
Expand Down Expand Up @@ -175,9 +173,8 @@ T* Statement::Bind(node::commons* com, const jxcore::PArguments& args,
last--;
}

T* baton = new T(this, callback);

JS_HANDLE_VALUE start_val = args.GetItem(start);
T* baton = new T(this, callback);

if (start < last) {
if (args.IsArray(start)) {
Expand All @@ -204,7 +201,7 @@ T* Statement::Bind(node::commons* com, const jxcore::PArguments& args,
if (JS_IS_INT32(name)) {
int32_t idn = INT32_TO_STD(name);
baton->parameters.push_back(
BindParameter(JS_GET_INDEX(object, idn), INT32_TO_STD(name)));
BindParameter(JS_GET_INDEX(object, idn), idn));
} else {
JS_LOCAL_STRING str_name = JS_VALUE_TO_STRING(name);
baton->parameters.push_back(BindParameter(
Expand Down Expand Up @@ -264,11 +261,11 @@ bool Statement::Bind(const Parameters& parameters) {
status = sqlite3_bind_null(handle, pos);
} break;
}
}

if (status != SQLITE_OK) {
message = std::string(sqlite3_errmsg(db->handle));
return false;
}
if (status != SQLITE_OK) {
message = std::string(sqlite3_errmsg(db->handle));
return false;
}
}

Expand Down Expand Up @@ -426,6 +423,7 @@ void Statement::Work_Run(uv_work_t* req) {
void Statement::Work_AfterRun(uv_work_t* req) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

STATEMENT_INIT(RunBaton);

if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
Expand Down Expand Up @@ -491,6 +489,7 @@ void Statement::Work_All(uv_work_t* req) {
void Statement::Work_AfterAll(uv_work_t* req) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

STATEMENT_INIT(RowsBaton);

if (stmt->status != SQLITE_DONE) {
Expand Down Expand Up @@ -698,8 +697,9 @@ void Statement::Work_AfterReset(uv_work_t* req) {
}

JS_LOCAL_OBJECT Statement::RowToJS(Row* row) {
JS_ENTER_SCOPE_COM();
node::commons* com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);

JS_LOCAL_OBJECT result = JS_NEW_EMPTY_OBJECT();

Row::const_iterator it = row->begin();
Expand Down Expand Up @@ -784,12 +784,13 @@ JS_METHOD(Statement, Finalize) {
JS_METHOD_END

void Statement::Finalize(Baton* baton) {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);
baton->stmt->Finalize();

// Fire callback in case there was one.
if (!JS_IS_EMPTY(baton->callback) && JS_IS_FUNCTION(baton->callback)) {
node::commons *com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);

TRY_CATCH_CALL_NO_PARAM(baton->stmt->handle_,
JS_TYPE_TO_LOCAL_FUNCTION(baton->callback));
}
Expand All @@ -809,10 +810,10 @@ void Statement::Finalize() {
}

void Statement::CleanQueue() {
JS_ENTER_SCOPE_COM();
JS_DEFINE_STATE_MARKER(com);

if (prepared && !queue.empty()) {
node::commons* com = node::commons::getInstance();
JS_DEFINE_STATE_MARKER(com);

// This statement has already been prepared and is now finalized.
// Fire error for all remaining items in the queue.
EXCEPTION("Statement is already finalized", SQLITE_MISUSE, exception);
Expand Down
Empty file modified src/external/sqlite3/statement.h
100644 → 100755
Empty file.

0 comments on commit a6f0ac6

Please sign in to comment.