Add support for transactions
Hey! I'd be happy to take this one if no one has.
Just to be sure I get the intention right.... the goal would be to introduce a simple, async-friendly API for beginning, committing, and rolling back transactions, while keeping the existing Execute methods unchanged. Right?
The new API could:
- Wrap standard BEGIN, COMMIT, and ROLLBACK commands
- Support await using semantics for automatic rollback if Commit() is never called
- Be extensible to future #20
Some planed changes:
- Add BeginTransaction() to IDatabaseClient, returning an ITransaction object
- Create ITransaction interface exposing:
- Execute(sql, args) for executing statements inside the transaction, and
- Commit() and Rollback() methods
- Implement Transaction class in DatabaseWrapper, using the existing Execute() under the hood but wrapping statements between BEGIN and COMMIT/ROLLBACK.
A usage example:
await using var client = await DatabaseClient.Create("file:my.db");
await using var tx = await client.BeginTransaction();
await tx.Execute("INSERT INTO books (title) VALUES (?)", "Pride and Prejudice");
await tx.Execute("INSERT INTO books (title) VALUES (?)", "Emma");
await tx.Commit(); // If not called, Rollback() is triggered automatically
If this approach looks good, I can work on this and open a PR when ready
That would be great. The proposed API sounds good. Regarding the implementation, up to now, the Database wrapper has been wrapping FFI calls to a dynamic library compiled from the libsql rust crate. The goal is to keep all of the logic upstream with the official crate and introduce only the C# flavour and usage of what is essentially the same functionality as offered by the rust crate.
The upstream libsql repository has C compatible functions written in the bindings directory which is what is bundled into this library. The libsql crate offers ways of working with transactions which I'd prefer to use.
If bindings for these usages already exist then implementation is just writing the API (interface) and performing FFI calls with the correct memory management. If the bindings do not yet exist then it'll mean asking the Turso team to implement it or provide a PR adding the necessary bindings in (unsafe) rust.
Thanks for your reply!
The goal is to keep all of the logic upstream with the official crate and introduce only the C# flavour and usage of what is essentially the same functionality as offered by the rust crate
Yes, that definitely sounds like the right approach.
If the bindings do not yet exist then it'll mean asking the Turso team to implement it
It looks like we'll probably need this, as I don't see connection_transaction or transaction_commit in the bindings. Please let me know if you plan to make the request to the Turso team, or I can handle it as well.
I have asked them about the status of C bindings while alerting them to an open PR I have for adding some related to the prepared statement feature. I'll update here when I get info.
If you see existing bindings which can enhance the functionality of this client library or feel like diving into writing unsafe rust code yourself then don't hold back 😊
Thanks!
waiting for https://github.com/tursodatabase/libsql/pull/2167