mixtape_tools/sqlite/transaction/
begin.rs1use crate::prelude::*;
4use crate::sqlite::manager::with_connection;
5
6#[derive(Debug, Deserialize, JsonSchema)]
8pub struct BeginTransactionInput {
9 #[serde(default)]
11 pub db_path: Option<String>,
12
13 #[serde(default)]
15 pub transaction_type: TransactionType,
16}
17
18#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)]
20#[serde(rename_all = "UPPERCASE")]
21pub enum TransactionType {
22 #[default]
24 Deferred,
25 Immediate,
27 Exclusive,
29}
30
31impl std::fmt::Display for TransactionType {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 TransactionType::Deferred => write!(f, "DEFERRED"),
35 TransactionType::Immediate => write!(f, "IMMEDIATE"),
36 TransactionType::Exclusive => write!(f, "EXCLUSIVE"),
37 }
38 }
39}
40
41pub struct BeginTransactionTool;
46
47impl Tool for BeginTransactionTool {
48 type Input = BeginTransactionInput;
49
50 fn name(&self) -> &str {
51 "sqlite_begin_transaction"
52 }
53
54 fn description(&self) -> &str {
55 "Begin a new database transaction. All subsequent operations will be part of this transaction until committed or rolled back."
56 }
57
58 async fn execute(&self, input: Self::Input) -> Result<ToolResult, ToolError> {
59 let tx_type = input.transaction_type;
60
61 with_connection(input.db_path, move |conn| {
62 let sql = format!("BEGIN {} TRANSACTION", tx_type);
63 conn.execute(&sql, [])?;
64 Ok(())
65 })
66 .await?;
67
68 let response = serde_json::json!({
69 "status": "success",
70 "message": format!("Transaction started ({})", tx_type)
71 });
72 Ok(ToolResult::Json(response))
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::sqlite::test_utils::TestDatabase;
80
81 #[tokio::test]
82 async fn test_begin_transaction() {
83 let db = TestDatabase::new().await;
84
85 let tool = BeginTransactionTool;
86 let input = BeginTransactionInput {
87 db_path: Some(db.key()),
88 transaction_type: TransactionType::Deferred,
89 };
90
91 let result = tool.execute(input).await;
92 assert!(result.is_ok());
93
94 db.execute("ROLLBACK");
96 }
97
98 #[test]
99 fn test_tool_metadata() {
100 let tool = BeginTransactionTool;
101 assert_eq!(tool.name(), "sqlite_begin_transaction");
102 assert!(!tool.description().is_empty());
103 }
104}