Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node:sqlite returning statement affects changes field in run() #57344

Open
sant123 opened this issue Mar 6, 2025 · 0 comments · May be fixed by #57350
Open

node:sqlite returning statement affects changes field in run() #57344

sant123 opened this issue Mar 6, 2025 · 0 comments · May be fixed by #57350
Labels
sqlite Issues and PRs related to the SQLite subsystem.

Comments

@sant123
Copy link

sant123 commented Mar 6, 2025

Version

v23.9.0

Platform

Linux jupiter 6.13.5-200.fc41.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Feb 27 15:07:31 UTC 2025 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

Please run this code:

import { DatabaseSync } from "node:sqlite";
const db = new DatabaseSync(":memory:");

db.exec(`CREATE TABLE people (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  birthdate TEXT NOT NULL
) STRICT`);

const insertPeople = db.prepare(`
INSERT INTO people
  (name, birthdate)
VALUES
  (:name, :birthdate)
RETURNING id
`);

const id1 = insertPeople.run({ name: "Flash", birthdate: "1956-07-16" });
const id2 = insertPeople.run({ name: "Bruno", birthdate: "1962-12-11" });
const id3 = insertPeople.run({ name: "Bruce", birthdate: "1963-06-17" });

console.log("id1", id1);
console.log("id2", id2);
console.log("id3", id3);

How often does it reproduce? Is there a required condition?

If RETURNING id is set in the query, the changes field is affected

What is the expected behavior? Why is that the expected behavior?

id1 { lastInsertRowid: 1, changes: 1 }
id2 { lastInsertRowid: 2, changes: 1 }
id3 { lastInsertRowid: 3, changes: 1 }

What do you see instead?

id1 { lastInsertRowid: 1, changes: 0 }
id2 { lastInsertRowid: 2, changes: 1 }
id3 { lastInsertRowid: 3, changes: 1 }

In id1, the changes field should be 1

Additional information

Using better-sqlite3 correctly handles it:

import Database from "better-sqlite3";
const db = new Database(":memory:");

Outputs:

id1 { changes: 1, lastInsertRowid: 1 }
id2 { changes: 1, lastInsertRowid: 2 }
id3 { changes: 1, lastInsertRowid: 3 }

@marco-ippolito marco-ippolito added the sqlite Issues and PRs related to the SQLite subsystem. label Mar 6, 2025
cjihrig added a commit to cjihrig/node that referenced this issue Mar 6, 2025
This commit updates StatementSync.prototype.run() to reset the
prepared statement immediately after calling sqlite3_step() to
return the correct change metadata.

Fixes: nodejs#57344
@cjihrig cjihrig linked a pull request Mar 6, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sqlite Issues and PRs related to the SQLite subsystem.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants