diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 98612f39695897..7fe616f454f753 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -2698,8 +2698,13 @@ MaybeLocal StatementExecutionHelper::Run(Environment* env, int r = sqlite3_reset(stmt); CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, MaybeLocal()); - sqlite3_int64 last_insert_rowid = sqlite3_last_insert_rowid(db->Connection()); - sqlite3_int64 changes = sqlite3_changes64(db->Connection()); + // Read-only statements (e.g. SELECT) never modify rows, so report 0 + // instead of leaking the count from the most recent write statement. + bool is_readonly = sqlite3_stmt_readonly(stmt); + sqlite3_int64 last_insert_rowid = + is_readonly ? 0 : sqlite3_last_insert_rowid(db->Connection()); + sqlite3_int64 changes = + is_readonly ? 0 : sqlite3_changes64(db->Connection()); Local last_insert_rowid_val; Local changes_val; diff --git a/test/parallel/test-sqlite-statement-sync.js b/test/parallel/test-sqlite-statement-sync.js index aa7a3a73ae6649..281f6366082b5c 100644 --- a/test/parallel/test-sqlite-statement-sync.js +++ b/test/parallel/test-sqlite-statement-sync.js @@ -909,3 +909,36 @@ suite('options.allowBareNamedParameters', () => { ); }); }); + +suite('read-only statements report zero changes', () => { + test('SELECT after INSERT reports zero changes', (t) => { + const db = new DatabaseSync(':memory:'); + t.after(() => { db.close(); }); + db.exec('CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)'); + const insert = db.prepare('INSERT INTO test (name) VALUES (?)'); + t.assert.deepStrictEqual( + insert.run('foo'), + { changes: 1, lastInsertRowid: 1 }, + ); + const select = db.prepare('SELECT * FROM test'); + t.assert.deepStrictEqual( + select.run(), + { changes: 0, lastInsertRowid: 0 }, + ); + }); + + test('SELECT after multiple INSERTs reports zero changes', (t) => { + const db = new DatabaseSync(':memory:'); + t.after(() => { db.close(); }); + db.exec('CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)'); + const insert = db.prepare('INSERT INTO test (name) VALUES (?)'); + insert.run('a'); + insert.run('b'); + insert.run('c'); + const select = db.prepare('SELECT * FROM test'); + t.assert.deepStrictEqual( + select.run(), + { changes: 0, lastInsertRowid: 0 }, + ); + }); +});