bind/rust: Add more tests for Transaction

This commit is contained in:
Diego Reis
2025-07-17 20:43:48 -03:00
parent 0b96c24196
commit 92cddb6437
2 changed files with 99 additions and 2 deletions

View File

@@ -36,6 +36,7 @@ pub mod params;
pub mod transaction;
pub mod value;
use transaction::TransactionBehavior;
pub use value::Value;
pub use params::params_from_iter;
@@ -132,6 +133,7 @@ impl Database {
#[allow(clippy::arc_with_non_send_sync)]
let connection = Connection {
inner: Arc::new(Mutex::new(conn)),
transaction_behavior: TransactionBehavior::Deferred,
};
Ok(connection)
}
@@ -140,12 +142,14 @@ impl Database {
/// A database connection.
pub struct Connection {
inner: Arc<Mutex<Arc<turso_core::Connection>>>,
transaction_behavior: TransactionBehavior,
}
impl Clone for Connection {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
transaction_behavior: self.transaction_behavior,
}
}
}

View File

@@ -288,7 +288,7 @@ impl Connection {
#[cfg(test)]
mod test {
use crate::{Builder, Connection, Result};
use crate::{Builder, Connection, Error, Result};
use super::DropBehavior;
@@ -299,18 +299,30 @@ mod test {
Ok(conn)
}
#[tokio::test]
#[should_panic(expected = "Transaction dropped without finish()")]
async fn test_drop_panic() {
let mut conn = checked_memory_handle().await.unwrap();
{
let tx = conn.transaction().await.unwrap();
tx.execute("INSERT INTO foo VALUES(?)", &[1]).await.unwrap();
}
}
#[tokio::test]
async fn test_drop() -> Result<()> {
let mut conn = checked_memory_handle().await?;
{
let tx = conn.transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[1]).await?;
tx.finish().await?;
// default: rollback
}
{
let mut tx = conn.transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[2]).await?;
tx.set_drop_behavior(DropBehavior::Commit)
tx.set_drop_behavior(DropBehavior::Commit);
tx.finish().await?;
}
{
let tx = conn.transaction().await?;
@@ -325,6 +337,87 @@ mod test {
.as_integer()
.unwrap()
);
tx.finish().await?;
}
Ok(())
}
fn assert_nested_tx_error(e: Error) {
if let Error::SqlExecutionFailure(e) = &e {
assert!(e.contains("transaction"));
} else {
panic!("Unexpected error type: {e:?}");
}
}
#[tokio::test]
async fn test_unchecked_nesting() -> Result<()> {
let conn = checked_memory_handle().await?;
{
let tx = conn.unchecked_transaction().await?;
let e = tx.unchecked_transaction().await.unwrap_err();
assert_nested_tx_error(e);
tx.finish().await?;
// default: rollback
}
{
let tx = conn.unchecked_transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[1]).await?;
// Ensure this doesn't interfere with ongoing transaction
let e = tx.unchecked_transaction().await.unwrap_err();
assert_nested_tx_error(e);
tx.execute("INSERT INTO foo VALUES(?)", &[1]).await?;
tx.commit().await?;
}
let mut result = conn.query("SELECT SUM(x) FROM foo", ()).await?;
assert_eq!(
2,
*result
.next()
.await?
.unwrap()
.get_value(0)?
.as_integer()
.unwrap()
);
Ok(())
}
#[tokio::test]
async fn test_explicit_rollback_commit() -> Result<()> {
let mut conn = checked_memory_handle().await?;
{
let tx = conn.transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[1]).await?;
tx.rollback().await?;
// This is a current Turso's limitation.
// Since we don't have support for savepoints yet,
// a rollback ends with a transaction so we need to immediately open a new one.
let tx = conn.transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[2]).await?;
tx.commit().await?;
}
{
let tx = conn.transaction().await?;
tx.execute("INSERT INTO foo VALUES(?)", &[4]).await?;
tx.commit().await?;
}
{
let mut result = conn.query("SELECT SUM(x) FROM foo", ()).await?;
assert_eq!(
2,
*result
.next()
.await?
.unwrap()
.get_value(0)?
.as_integer()
.unwrap()
);
}
Ok(())
}