-
Notifications
You must be signed in to change notification settings - Fork 7
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
use uuid as savepoint name #32
Conversation
packages/crsqlite-wasm/src/TX.ts
Outdated
throw e; | ||
} finally { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want finally here.
finally will run even after catch
which means that we'll rollback
(if there was an exception) and then release
. We just want to do one or the other.
What problems were you experiencing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, let me elaborate on the OP. From the docs:
The ROLLBACK command with a TO clause rolls back transactions going backwards in time back to the most recent SAVEPOINT with a matching name. The SAVEPOINT with the matching name remains on the transaction stack.
Emphasis mine. Since that SAVEPOINT remains on the stack, we must RELEASE to close out that savepoint.
The RELEASE command starts with the most recent addition to the transaction stack and releases savepoints backwards in time until it releases a savepoint with a matching savepoint-name.
However, I'm now thinking about what happens if the ROLLBACK fails - with finally
we RELEASE without a ROLLBACK. That's undesirable. If the ROLLBACK fails, we should just throw. The new commit reflects this realization.
What problems were you experiencing?
No problems on the application side - I started to investigate nested transactions, so just read the docs and other people's code (including this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Thanks so much for pointing this out. I had no idea that it remained on the stack (illustrated below).
try { | ||
await cb(tx); | ||
} catch (e) { | ||
await tx.exec("ROLLBACK"); | ||
await tx.exec("ROLLBACK TO " + id); | ||
await tx.exec("RELEASE " + id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh interesting.. I had the completely wrong mental model of savepoints
and didn't realize a rollback
needs to be followed by a release
to actually pop it off the stack o_O
Thanks for catching this.
sqlite> savepoint b;
sqlite> create table boo (a);
sqlite> rollback to b;
sqlite> create table bar (a);
sqlite> release b;
sqlite> .tables
bar foo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better illustration:
sqlite> savepoint b;
sqlite> savepoint b;
sqlite> rollback to b;
sqlite> release b;
sqlite> release b;
sqlite> release b;
Runtime error: no such savepoint: b
Even with rollback
we must release
I'll merge this today. I also need to update core extension code in |
Gonna assume here that
in the failed run is due to starting with a numeric
|
Learned more about ROLLBACK TO here: vlcn-io/js#32 What we really want is to abort all transactions if any of these operations fails. Switching to `ROLLBACK`
Learned more about ROLLBACK TO here: vlcn-io/js#32 What we really want is to abort all transactions if any of these operations fails. Switching to `ROLLBACK`
The primary cause of this PR is this line from the docs:
I think the current behavior of busting out of all transactions seems too much. Note that even though the rollback causes "The SAVEPOINT with the matching name [to] remains on the transaction stack", the subsequent RELEASE on L109 will (more or less) close out the transaction and commit nothing. I think. I've tested nothing 😅
I also made the names UUIDs because even though "The transaction names need not be unique", it just feels safer. Feel free to assuage me of my paranoia.