Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 57 additions & 15 deletions src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ inline MaybeLocal<String> Utf8StringMaybeOneByte(Isolate* isolate,
} \
} while (0)

#define RESET_OR_THROW(isolate, db, stmt, ret) \
CHECK_ERROR_OR_THROW((isolate), (db), sqlite3_reset((stmt)), SQLITE_OK, (ret))

// Surface deferred SQLite errors that sqlite3_reset() returns from the prior
// sqlite3_step(). Disables the safety-net reset guard via |needs_reset|.
#define RESET_AND_CHECK(isolate, db, stmt, needs_reset, ret) \
do { \
(needs_reset) = false; \
RESET_OR_THROW((isolate), (db), (stmt), (ret)); \
} while (0)

#define THROW_AND_RETURN_ON_BAD_STATE(env, condition, msg) \
do { \
if ((condition)) { \
Expand Down Expand Up @@ -2893,9 +2904,17 @@ MaybeLocal<Object> StatementExecutionHelper::Run(Environment* env,
bool use_big_ints) {
Isolate* isolate = env->isolate();
EscapableHandleScope scope(isolate);
sqlite3_step(stmt);
int r = sqlite3_reset(stmt);
CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, MaybeLocal<Object>());
bool needs_reset = true;
auto reset = OnScopeLeave([&]() {
if (needs_reset) sqlite3_reset(stmt);
});

int step_r = sqlite3_step(stmt);
if (step_r != SQLITE_DONE && step_r != SQLITE_ROW) {
THROW_ERR_SQLITE_ERROR(isolate, db);
return MaybeLocal<Object>();
}
RESET_AND_CHECK(isolate, db, stmt, needs_reset, MaybeLocal<Object>());

sqlite3_int64 last_insert_rowid = sqlite3_last_insert_rowid(db->Connection());
sqlite3_int64 changes = sqlite3_changes64(db->Connection());
Expand Down Expand Up @@ -2969,18 +2988,25 @@ MaybeLocal<Value> StatementExecutionHelper::Get(Environment* env,
bool use_big_ints) {
Isolate* isolate = env->isolate();
EscapableHandleScope scope(isolate);
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt); });
bool needs_reset = true;
auto reset = OnScopeLeave([&]() {
if (needs_reset) sqlite3_reset(stmt);
});

int r = sqlite3_step(stmt);
if (r == SQLITE_DONE) return scope.Escape(Undefined(isolate));
if (r == SQLITE_DONE) {
RESET_AND_CHECK(isolate, db, stmt, needs_reset, MaybeLocal<Value>());
return scope.Escape(Undefined(isolate));
}
if (r != SQLITE_ROW) {
THROW_ERR_SQLITE_ERROR(isolate, db);
return MaybeLocal<Value>();
}

int num_cols = sqlite3_column_count(stmt);
if (num_cols == 0) {
return Undefined(isolate);
RESET_AND_CHECK(isolate, db, stmt, needs_reset, MaybeLocal<Value>());
return scope.Escape(Undefined(isolate));
}

LocalVector<Value> row_values(isolate);
Expand All @@ -2989,9 +3015,9 @@ MaybeLocal<Value> StatementExecutionHelper::Get(Environment* env,
return MaybeLocal<Value>();
}

Local<Value> result;
if (return_arrays) {
return scope.Escape(
Array::New(isolate, row_values.data(), row_values.size()));
result = Array::New(isolate, row_values.data(), row_values.size());
} else {
LocalVector<Name> keys(isolate);
keys.reserve(num_cols);
Expand All @@ -3004,9 +3030,12 @@ MaybeLocal<Value> StatementExecutionHelper::Get(Environment* env,
}

DCHECK_EQ(keys.size(), row_values.size());
return scope.Escape(Object::New(
isolate, Null(isolate), keys.data(), row_values.data(), num_cols));
result = Object::New(
isolate, Null(isolate), keys.data(), row_values.data(), num_cols);
}

RESET_AND_CHECK(isolate, db, stmt, needs_reset, MaybeLocal<Value>());
return scope.Escape(result);
}

void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
Expand All @@ -3023,15 +3052,19 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
return;
}

auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });

bool needs_reset = true;
auto reset = OnScopeLeave([&]() {
if (needs_reset) sqlite3_reset(stmt->statement_);
});
Local<Value> result;
if (StatementExecutionHelper::All(env,
stmt->db_.get(),
stmt->statement_,
stmt->return_arrays_,
stmt->use_big_ints_)
.ToLocal(&result)) {
RESET_AND_CHECK(
isolate, stmt->db_.get(), stmt->statement_, needs_reset, void());
args.GetReturnValue().Set(result);
}
}
Expand Down Expand Up @@ -3470,14 +3503,19 @@ void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) {
}
}

auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
bool needs_reset = true;
auto reset = OnScopeLeave([&]() {
if (needs_reset) sqlite3_reset(stmt->statement_);
});
Local<Value> result;
if (StatementExecutionHelper::All(env,
stmt->db_.get(),
stmt->statement_,
stmt->return_arrays_,
stmt->use_big_ints_)
.ToLocal(&result)) {
RESET_AND_CHECK(
isolate, stmt->db_.get(), stmt->statement_, needs_reset, void());
args.GetReturnValue().Set(result);
}
}
Expand Down Expand Up @@ -3702,7 +3740,10 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
if (r != SQLITE_ROW) {
CHECK_ERROR_OR_THROW(
env->isolate(), iter->stmt_->db_.get(), r, SQLITE_DONE, void());
sqlite3_reset(iter->stmt_->statement_);
RESET_OR_THROW(env->isolate(),
iter->stmt_->db_.get(),
iter->stmt_->statement_,
void());
MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};
Local<Object> result;
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
Expand Down Expand Up @@ -3754,7 +3795,8 @@ void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
env, iter->stmt_->IsFinalized(), "statement has been finalized");
Isolate* isolate = env->isolate();

sqlite3_reset(iter->stmt_->statement_);
RESET_OR_THROW(
isolate, iter->stmt_->db_.get(), iter->stmt_->statement_, void());
iter->done_ = true;

auto iter_template = getLazyIterTemplate(env);
Expand Down
Loading