Skip to content

Commit bf13e4c

Browse files
committed
sqlite: isolate applyChangeset filter errors
Track filter callback failures within each applyChangeset() invocation. Returning false from xFilter is not a SQLite error. This previously left the database-wide suppression flag set, which could hide the next unrelated SQLite error. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol
1 parent a6e7e6a commit bf13e4c

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

src/node_sqlite.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,6 +2277,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
22772277

22782278
Local<Function> conflictFunc;
22792279
Local<Function> filterFunc;
2280+
bool filterCallbackFailed = false;
22802281
if (args.Length() > 1 && !args[1]->IsUndefined()) {
22812282
if (!args[1]->IsObject()) {
22822283
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
@@ -2338,25 +2339,25 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
23382339

23392340
filterFunc = filterValue.As<Function>();
23402341

2341-
context.filterCallback =
2342-
[env, db, &filterFunc](std::string_view item) -> bool {
2342+
context.filterCallback = [env, &filterFunc, &filterCallbackFailed](
2343+
std::string_view item) -> bool {
23432344
// If there was an error in the previous call to the filter's
23442345
// callback, we skip calling it again.
2345-
if (db->ignore_next_sqlite_error_) {
2346+
if (filterCallbackFailed) {
23462347
return false;
23472348
}
23482349

23492350
Local<Value> argv[1];
23502351
if (!ToV8Value(env->context(), item, env->isolate())
23512352
.ToLocal(&argv[0])) {
2352-
db->SetIgnoreNextSQLiteError(true);
2353+
filterCallbackFailed = true;
23532354
return false;
23542355
}
23552356

23562357
Local<Value> result;
23572358
if (!filterFunc->Call(env->context(), Null(env->isolate()), 1, argv)
23582359
.ToLocal(&result)) {
2359-
db->SetIgnoreNextSQLiteError(true);
2360+
filterCallbackFailed = true;
23602361
return false;
23612362
}
23622363

test/parallel/test-sqlite-session.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,13 @@ test('filter handler throws', (t) => {
388388
name: 'Error',
389389
message: 'Error filtering table data1'
390390
});
391+
392+
t.assert.throws(() => {
393+
database2.exec('CREATE TABLEEEE');
394+
}, {
395+
code: 'ERR_SQLITE_ERROR',
396+
message: /syntax error/,
397+
});
391398
});
392399

393400
test('database.createSession() - filter changes', (t) => {

0 commit comments

Comments
 (0)