-
Notifications
You must be signed in to change notification settings - Fork 31.3k
sqlite: StatementSync#iterate
fails with Error: statement has been finalized
#57493
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
Comments
cc: @tpoisseau |
Hello, Today I don't know when I will have time to work on this, v8 CPP is really hard for me. It look like, somewhere, the statement is closed / free during the iteration. I have no idea why. |
I think the problem is the iterator doesn't have a reference to the Proof: edit the code to this: const stmt = database.prepare("SELECT * from users;");
const iter = stmt.iterate(); That seems to work till the cows come home, because I'm now hanging on to I imagine the solution is to create a ref to the |
@fuchsia I believe your assessment is correct. The only thing I'd add is that the iterator can hold a reference to the |
I expect to have some time next week when I could have a go at writing a fix. I've not built node before, and getting my system set up to do that is the most daunting bit! I've plenty of experience of C++ and using sqlite3 from C++, although it's a bit rusty. |
This commit refactors the StatementSync iterator implementation in two primary ways: - The iterator internal state is no longer exposed to JavaScript. - The iterator prevents the prepared statement from being GC'ed. Fixes: nodejs#57493
I just encountered this issue while working on https://github.com/ducktors/Valkeyrie I have this test case that returns this error while I would expect a different one. Something like "Error: the db is closed', but it throws "Error: statement has been finalized" instead. This is the test case: await test('Valkeyrie explicit resource management', async () => {
let db2: Valkeyrie
{
await using db = await Valkeyrie.open()
db2 = db
const res = await db.get(['a'])
assert.strictEqual(res.versionstamp, null)
}
await assert.rejects(() => db2.get(['a']), Error)
}) Is this the expected behavior? Do I need to track the status of the database in the user land? |
@fox1t what you're seeing is not the same as this issue, which is specific to
You're using an additional API on top of
If you try to use a database after it's closed, you get a message that the database is closed. If you try to use an individual prepared statement after the database is closed or the statement is otherwise finalized, you get the finalized error.
No, you shouldn't need to. There is also going to be a method for this in the next release (#57522). |
Oh, @cjihrig, that's awesome. Thanks for sharing this info about the finalization of the statements. I didn't realize it until now. That's exactly what happens since I prepare all queries at the "driver" level. It is a tiny wrapper of the underlying backend (SQLite in this case) that doesn't add any logic. It's cool that isOpen is being added! |
This commit refactors the StatementSync iterator implementation in two primary ways: - The iterator internal state is no longer exposed to JavaScript. - The iterator prevents the prepared statement from being GC'ed. Fixes: nodejs#57493 PR-URL: nodejs#57569 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Edy Silva <[email protected]> Reviewed-By: Zeyu "Alex" Yang <[email protected]>
Version
v23.10.0
Platform
Subsystem
sqlite
What steps will reproduce the bug?
index.js
How often does it reproduce? Is there a required condition?
Happens every time. Sometimes it errors, sometimes it just stops unexpectedly without an error.
It doesn't reproduce if you uncomment the line where I fetch all rows immediately by spreading it into an array and then turning it back into an iterator, so the issue comes from reading each value over time.
What is the expected behavior? Why is that the expected behavior?
It should not error and it should print 1000 rows.
What do you see instead?
90% of runs
OR
10% it just stops without an error. It should have printed up to 1000.
Sometimes the values of the last "successful" row is garbage. Sometimes for
name
it printsundefined
or something likeÙÙ¥Ñ88
. The name should always match0-9a-z
so there is some sort of corruption, too.Additional information
You can see on the Ubuntu run, it exits with an error. On the Windows run, it just exits for no apparent reason. That is random, though, not platform-dependent.
The text was updated successfully, but these errors were encountered: