Skip to content

Commit b23f1f4

Browse files
danielnorbergclaude
andcommitted
[spanner] Add transaction() accessor method to TransactionManager
Features: - Add transaction() method that returns Option<&mut ReadWriteTransaction> - Returns None if no transaction is active, Some if active - Enables checking transaction state and accessing existing transaction - Includes comprehensive test coverage Use cases: - Check if a transaction exists without starting one - Access existing transaction for additional operations - Conditional logic based on transaction state Test added: - test_transaction_accessor() validates behavior before/after begin - Tests functional access through the accessor - Verifies data written through accessor is committed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 8a4a3e5 commit b23f1f4

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

spanner/src/transaction_manager.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ impl TransactionManager {
4444
}
4545
}
4646

47+
/// Returns a mutable reference to the current transaction, if one has been started.
48+
///
49+
/// Returns `None` if no transaction is currently active. Call
50+
/// `begin_read_write_transaction()` to start a new transaction.
51+
///
52+
/// # Example
53+
///
54+
/// ```rust,ignore
55+
/// let mut tm = client.transaction_manager().await?;
56+
///
57+
/// // Initially returns None
58+
/// assert!(tm.transaction().is_none());
59+
///
60+
/// // After begin, returns Some
61+
/// let tx = tm.begin_read_write_transaction().await?;
62+
/// assert!(tm.transaction().is_some());
63+
/// ```
64+
pub fn transaction(&mut self) -> Option<&mut ReadWriteTransaction> {
65+
self.transaction.as_mut()
66+
}
67+
4768
/// Begins a new read-write transaction, reusing the session from the
4869
/// previous transaction if one exists. Returns a mutable reference to
4970
/// the transaction which can be used to execute queries and mutations.

spanner/tests/transaction_manager_test.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,61 @@ async fn verify_transaction_manager_data(
255255
);
256256
assert!(user_characters.is_empty());
257257
}
258+
259+
#[tokio::test]
260+
#[serial]
261+
async fn test_transaction_accessor() {
262+
// Set up test data
263+
let now = OffsetDateTime::now_utc();
264+
let data_client = create_data_client().await;
265+
let user_id = format!("user_tm_accessor_{}", now.unix_timestamp());
266+
267+
data_client
268+
.apply(vec![create_user_mutation(&user_id, &now)])
269+
.await
270+
.unwrap();
271+
272+
// Test transaction accessor method
273+
let mut tm = data_client.transaction_manager().await.unwrap();
274+
275+
// Initially should return None
276+
assert!(tm.transaction().is_none());
277+
278+
// Begin a transaction
279+
let _tx = tm.begin_read_write_transaction().await.unwrap();
280+
281+
// Now should return Some
282+
assert!(tm.transaction().is_some());
283+
284+
// Should be able to use the accessor to perform operations
285+
if let Some(tx) = tm.transaction() {
286+
let mut stmt = Statement::new(
287+
"INSERT INTO UserItem (UserId,ItemId,Quantity,UpdatedAt) \
288+
VALUES(@UserId,999,123,PENDING_COMMIT_TIMESTAMP())",
289+
);
290+
stmt.add_param("UserId", &user_id);
291+
tx.update(stmt).await.unwrap();
292+
293+
// Commit via the accessor
294+
let result: Result<(), google_cloud_spanner::client::Error> = Ok(());
295+
match tx.end(result, None).await {
296+
Ok(_) => (),
297+
Err(err) => panic!("Commit failed: {:?}", err),
298+
}
299+
}
300+
301+
// Verify the data was actually written
302+
let mut tx = data_client.read_only_transaction().await.unwrap();
303+
let mut stmt = Statement::new(
304+
"SELECT * FROM UserItem WHERE UserId = @UserId AND ItemId = 999",
305+
);
306+
stmt.add_param("UserId", &user_id);
307+
308+
let reader = tx.query(stmt).await.unwrap();
309+
let rows: Vec<Row> = all_rows(reader).await.unwrap();
310+
311+
assert_eq!(1, rows.len());
312+
let row = rows.first().unwrap();
313+
assert_eq!(row.column_by_name::<i64>("ItemId").unwrap(), 999);
314+
assert_eq!(row.column_by_name::<i64>("Quantity").unwrap(), 123);
315+
}

0 commit comments

Comments
 (0)