use crate::prelude::*;
use crate::sqlite::manager::with_connection;
#[derive(Debug, Deserialize, JsonSchema)]
pub struct RollbackTransactionInput {
#[serde(default)]
pub db_path: Option<String>,
}
pub struct RollbackTransactionTool;
impl Tool for RollbackTransactionTool {
type Input = RollbackTransactionInput;
fn name(&self) -> &str {
"sqlite_rollback_transaction"
}
fn description(&self) -> &str {
"Rollback the current transaction, reverting all changes made since the transaction began."
}
async fn execute(&self, input: Self::Input) -> Result<ToolResult, ToolError> {
with_connection(input.db_path, |conn| {
conn.execute("ROLLBACK", [])?;
Ok(())
})
.await?;
let response = serde_json::json!({
"status": "success",
"message": "Transaction rolled back successfully"
});
Ok(ToolResult::Json(response))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sqlite::test_utils::TestDatabase;
use crate::sqlite::transaction::BeginTransactionTool;
#[tokio::test]
async fn test_rollback_transaction() {
let db = TestDatabase::with_schema("CREATE TABLE test (id INTEGER);").await;
let begin_tool = BeginTransactionTool;
let begin_input = crate::sqlite::transaction::begin::BeginTransactionInput {
db_path: Some(db.key()),
transaction_type: crate::sqlite::transaction::begin::TransactionType::Deferred,
};
begin_tool.execute(begin_input).await.unwrap();
db.execute("INSERT INTO test VALUES (1)");
db.execute("INSERT INTO test VALUES (2)");
let tool = RollbackTransactionTool;
let input = RollbackTransactionInput {
db_path: Some(db.key()),
};
let result = tool.execute(input).await;
assert!(result.is_ok());
assert_eq!(db.count("test"), 0);
}
#[test]
fn test_tool_metadata() {
let tool = RollbackTransactionTool;
assert_eq!(tool.name(), "sqlite_rollback_transaction");
assert!(!tool.description().is_empty());
}
}