toasty_driver_integration_suite/tests/
tx_interactive.rs1use crate::prelude::*;
2
3use toasty_core::driver::{Operation, operation::IsolationLevel, operation::Transaction};
4
5#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
9pub async fn commit_persists_data(t: &mut Test) -> Result<()> {
10 let mut db = setup(t).await;
11
12 let mut tx = db.transaction().await?;
13 User::create().name("Alice").exec(&mut tx).await?;
14 tx.commit().await?;
15
16 let users = User::all().exec(&mut db).await?;
17 assert_eq!(users.len(), 1);
18 assert_eq!(users[0].name, "Alice");
19
20 Ok(())
21}
22
23#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
25pub async fn rollback_discards_data(t: &mut Test) -> Result<()> {
26 let mut db = setup(t).await;
27
28 let mut tx = db.transaction().await?;
29 User::create().name("Ghost").exec(&mut tx).await?;
30 tx.rollback().await?;
31
32 let users = User::all().exec(&mut db).await?;
33 assert!(users.is_empty());
34
35 Ok(())
36}
37
38#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
40pub async fn drop_without_finalize_rolls_back(t: &mut Test) -> Result<()> {
41 let mut db = setup(t).await;
42
43 {
44 let mut tx = db.transaction().await?;
45 User::create().name("Ghost").exec(&mut tx).await?;
46 }
48
49 let users = User::all().exec(&mut db).await?;
50 assert!(users.is_empty());
51
52 Ok(())
53}
54
55#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
57pub async fn multiple_ops_in_transaction(t: &mut Test) -> Result<()> {
58 let mut db = setup(t).await;
59
60 let mut tx = db.transaction().await?;
61 User::create().name("Alice").exec(&mut tx).await?;
62 User::create().name("Bob").exec(&mut tx).await?;
63 User::create().name("Carol").exec(&mut tx).await?;
64 tx.commit().await?;
65
66 let users = User::all().exec(&mut db).await?;
67 assert_eq!(users.len(), 3);
68
69 Ok(())
70}
71
72#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
75pub async fn read_your_writes(t: &mut Test) -> Result<()> {
76 let mut db = setup(t).await;
77
78 let mut tx = db.transaction().await?;
79 User::create().name("Alice").exec(&mut tx).await?;
80
81 let users = User::all().exec(&mut tx).await?;
82 assert_eq!(users.len(), 1);
83 assert_eq!(users[0].name, "Alice");
84
85 tx.commit().await?;
86
87 Ok(())
88}
89
90#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
92pub async fn update_inside_transaction(t: &mut Test) -> Result<()> {
93 let mut db = setup(t).await;
94
95 let mut user = User::create().name("Alice").exec(&mut db).await?;
96
97 let mut tx = db.transaction().await?;
98 user.update().name("Bob").exec(&mut tx).await?;
99 tx.commit().await?;
100
101 let reloaded = User::get_by_id(&mut db, user.id).await?;
102 assert_eq!(reloaded.name, "Bob");
103
104 Ok(())
105}
106
107#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
109pub async fn update_rolled_back(t: &mut Test) -> Result<()> {
110 let mut db = setup(t).await;
111
112 let mut user = User::create().name("Alice").exec(&mut db).await?;
113
114 let mut tx = db.transaction().await?;
115 user.update().name("Bob").exec(&mut tx).await?;
116 tx.rollback().await?;
117
118 let reloaded = User::get_by_id(&mut db, user.id).await?;
119 assert_eq!(reloaded.name, "Alice");
120
121 Ok(())
122}
123
124#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
126pub async fn delete_rolled_back(t: &mut Test) -> Result<()> {
127 let mut db = setup(t).await;
128
129 let user = User::create().name("Alice").exec(&mut db).await?;
130
131 let mut tx = db.transaction().await?;
132 User::filter_by_id(user.id).delete().exec(&mut tx).await?;
133 tx.rollback().await?;
134
135 let reloaded = User::get_by_id(&mut db, user.id).await?;
136 assert_eq!(reloaded.name, "Alice");
137
138 Ok(())
139}
140
141#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
145pub async fn driver_sees_begin_commit(t: &mut Test) -> Result<()> {
146 let mut db = setup(t).await;
147
148 t.log().clear();
149
150 let mut tx = db.transaction().await?;
151 User::create().name("Alice").exec(&mut tx).await?;
152 tx.commit().await?;
153
154 assert_struct!(
155 t.log().pop_op(),
156 Operation::Transaction(Transaction::Start {
157 isolation: None,
158 read_only: false
159 })
160 );
161 assert_struct!(t.log().pop_op(), Operation::QuerySql(_)); assert_struct!(
163 t.log().pop_op(),
164 Operation::Transaction(Transaction::Commit)
165 );
166 assert!(t.log().is_empty());
167
168 Ok(())
169}
170
171#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
173pub async fn driver_sees_begin_rollback(t: &mut Test) -> Result<()> {
174 let mut db = setup(t).await;
175
176 t.log().clear();
177
178 let mut tx = db.transaction().await?;
179 User::create().name("Alice").exec(&mut tx).await?;
180 tx.rollback().await?;
181
182 assert_struct!(
183 t.log().pop_op(),
184 Operation::Transaction(Transaction::Start {
185 isolation: None,
186 read_only: false
187 })
188 );
189 assert_struct!(t.log().pop_op(), Operation::QuerySql(_)); assert_struct!(
191 t.log().pop_op(),
192 Operation::Transaction(Transaction::Rollback)
193 );
194 assert!(t.log().is_empty());
195
196 Ok(())
197}
198
199#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
204pub async fn nested_commit_both(t: &mut Test) -> Result<()> {
205 let mut db = setup(t).await;
206
207 let mut tx = db.transaction().await?;
208 User::create().name("Alice").exec(&mut tx).await?;
209
210 {
211 let mut nested = tx.transaction().await?;
212 User::create().name("Bob").exec(&mut nested).await?;
213 nested.commit().await?;
214 }
215
216 tx.commit().await?;
217
218 let users = User::all().exec(&mut db).await?;
219 assert_eq!(users.len(), 2);
220
221 Ok(())
222}
223
224#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
227pub async fn nested_rollback_inner(t: &mut Test) -> Result<()> {
228 let mut db = setup(t).await;
229
230 let mut tx = db.transaction().await?;
231 User::create().name("Alice").exec(&mut tx).await?;
232
233 {
234 let mut nested = tx.transaction().await?;
235 User::create().name("Ghost").exec(&mut nested).await?;
236 nested.rollback().await?;
237 }
238
239 tx.commit().await?;
240
241 let users = User::all().exec(&mut db).await?;
242 assert_eq!(users.len(), 1);
243 assert_eq!(users[0].name, "Alice");
244
245 Ok(())
246}
247
248#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
251pub async fn nested_rollback_outer(t: &mut Test) -> Result<()> {
252 let mut db = setup(t).await;
253
254 let mut tx = db.transaction().await?;
255 User::create().name("Alice").exec(&mut tx).await?;
256
257 {
258 let mut nested = tx.transaction().await?;
259 User::create().name("Bob").exec(&mut nested).await?;
260 nested.commit().await?;
261 }
262
263 tx.rollback().await?;
264
265 let users = User::all().exec(&mut db).await?;
266 assert!(users.is_empty());
267
268 Ok(())
269}
270
271#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
274pub async fn nested_drop_rolls_back_savepoint(t: &mut Test) -> Result<()> {
275 let mut db = setup(t).await;
276
277 let mut tx = db.transaction().await?;
278 User::create().name("Alice").exec(&mut tx).await?;
279
280 {
281 let mut nested = tx.transaction().await?;
282 User::create().name("Ghost").exec(&mut nested).await?;
283 }
285
286 tx.commit().await?;
287
288 let users = User::all().exec(&mut db).await?;
289 assert_eq!(users.len(), 1);
290 assert_eq!(users[0].name, "Alice");
291
292 Ok(())
293}
294
295#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
298pub async fn nested_driver_sees_savepoint_ops(t: &mut Test) -> Result<()> {
299 let mut db = setup(t).await;
300
301 t.log().clear();
302
303 let mut tx = db.transaction().await?;
304 User::create().name("Alice").exec(&mut tx).await?;
305
306 let mut nested = tx.transaction().await?;
307 User::create().name("Bob").exec(&mut nested).await?;
308 nested.commit().await?;
309
310 tx.commit().await?;
311
312 assert_struct!(
314 t.log().pop_op(),
315 Operation::Transaction(Transaction::Start {
316 isolation: None,
317 read_only: false
318 })
319 );
320 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
322 assert_struct!(
324 t.log().pop_op(),
325 Operation::Transaction(Transaction::Savepoint(_))
326 );
327 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
329 assert_struct!(
331 t.log().pop_op(),
332 Operation::Transaction(Transaction::ReleaseSavepoint(_))
333 );
334 assert_struct!(
336 t.log().pop_op(),
337 Operation::Transaction(Transaction::Commit)
338 );
339 assert!(t.log().is_empty());
340
341 Ok(())
342}
343
344#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
347pub async fn nested_driver_sees_rollback_to_savepoint(t: &mut Test) -> Result<()> {
348 let mut db = setup(t).await;
349
350 t.log().clear();
351
352 let mut tx = db.transaction().await?;
353
354 let mut nested = tx.transaction().await?;
355 User::create().name("Ghost").exec(&mut nested).await?;
356 nested.rollback().await?;
357
358 tx.commit().await?;
359
360 assert_struct!(
362 t.log().pop_op(),
363 Operation::Transaction(Transaction::Start {
364 isolation: None,
365 read_only: false
366 })
367 );
368 assert_struct!(
370 t.log().pop_op(),
371 Operation::Transaction(Transaction::Savepoint(_))
372 );
373 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
375 assert_struct!(
377 t.log().pop_op(),
378 Operation::Transaction(Transaction::RollbackToSavepoint(_))
379 );
380 assert_struct!(
382 t.log().pop_op(),
383 Operation::Transaction(Transaction::Commit)
384 );
385 assert!(t.log().is_empty());
386
387 Ok(())
388}
389
390#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
393pub async fn two_sequential_nested_transactions(t: &mut Test) -> Result<()> {
394 let mut db = setup(t).await;
395
396 let mut tx = db.transaction().await?;
397
398 {
399 let mut nested1 = tx.transaction().await?;
400 User::create().name("Alice").exec(&mut nested1).await?;
401 nested1.commit().await?;
402 }
403
404 {
405 let mut nested2 = tx.transaction().await?;
406 User::create().name("Ghost").exec(&mut nested2).await?;
407 nested2.rollback().await?;
408 }
409
410 tx.commit().await?;
411
412 let users = User::all().exec(&mut db).await?;
413 assert_eq!(users.len(), 1);
414 assert_eq!(users[0].name, "Alice");
415
416 Ok(())
417}
418
419#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
425pub async fn multi_op_inside_tx_uses_savepoints(t: &mut Test) -> Result<()> {
426 let mut db = setup(t).await;
427
428 t.log().clear();
429
430 let mut tx = db.transaction().await?;
431 let user = User::create()
432 .name("Alice")
433 .todo(Todo::create().title("task"))
434 .exec(&mut tx)
435 .await?;
436 tx.commit().await?;
437
438 assert_struct!(
440 t.log().pop_op(),
441 Operation::Transaction(Transaction::Start {
442 isolation: None,
443 read_only: false
444 })
445 );
446 assert_struct!(
448 t.log().pop_op(),
449 Operation::Transaction(Transaction::Savepoint(_))
450 );
451 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
453 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
455 assert_struct!(
457 t.log().pop_op(),
458 Operation::Transaction(Transaction::ReleaseSavepoint(_))
459 );
460 assert_struct!(
462 t.log().pop_op(),
463 Operation::Transaction(Transaction::Commit)
464 );
465 assert!(t.log().is_empty());
466
467 let todos = user.todos().exec(&mut db).await?;
469 assert_eq!(todos.len(), 1);
470 assert_eq!(todos[0].title, "task");
471
472 Ok(())
473}
474
475#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
479pub async fn builder_on_db_commit(t: &mut Test) -> Result<()> {
480 let mut db = setup(t).await;
481
482 let mut tx = db.transaction_builder().begin().await?;
483 User::create().name("Alice").exec(&mut tx).await?;
484 tx.commit().await?;
485
486 let users = User::all().exec(&mut db).await?;
487 assert_eq!(users.len(), 1);
488 assert_eq!(users[0].name, "Alice");
489
490 Ok(())
491}
492
493#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
495pub async fn builder_on_connection_commit(t: &mut Test) -> Result<()> {
496 let db = setup(t).await;
497 let mut conn = db.connection().await?;
498
499 let mut tx = conn.transaction_builder().begin().await?;
500 User::create().name("Alice").exec(&mut tx).await?;
501 tx.commit().await?;
502
503 let users = User::all().exec(&mut conn).await?;
504 assert_eq!(users.len(), 1);
505 assert_eq!(users[0].name, "Alice");
506
507 Ok(())
508}
509
510#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
512pub async fn builder_with_isolation_level(t: &mut Test) -> Result<()> {
513 let mut db = setup(t).await;
514
515 t.log().clear();
516
517 let mut tx = db
518 .transaction_builder()
519 .isolation(IsolationLevel::Serializable)
520 .begin()
521 .await?;
522 User::create().name("Alice").exec(&mut tx).await?;
523 tx.commit().await?;
524
525 assert_struct!(
526 t.log().pop_op(),
527 Operation::Transaction(Transaction::Start {
528 isolation: Some(IsolationLevel::Serializable),
529 read_only: false
530 })
531 );
532
533 Ok(())
534}
535
536#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
538pub async fn builder_with_read_only(t: &mut Test) -> Result<()> {
539 let mut db = setup(t).await;
540
541 t.log().clear();
542
543 let tx = db.transaction_builder().read_only(true).begin().await?;
544 tx.commit().await?;
545
546 assert_struct!(
547 t.log().pop_op(),
548 Operation::Transaction(Transaction::Start {
549 isolation: None,
550 read_only: true
551 })
552 );
553
554 Ok(())
555}
556
557#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
559pub async fn builder_with_all_options(t: &mut Test) -> Result<()> {
560 let mut db = setup(t).await;
561
562 t.log().clear();
563
564 let tx = db
565 .transaction_builder()
566 .isolation(IsolationLevel::Serializable)
567 .read_only(true)
568 .begin()
569 .await?;
570 tx.commit().await?;
571
572 assert_struct!(
573 t.log().pop_op(),
574 Operation::Transaction(Transaction::Start {
575 isolation: Some(IsolationLevel::Serializable),
576 read_only: true
577 })
578 );
579
580 Ok(())
581}
582
583#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
585pub async fn builder_drop_rolls_back(t: &mut Test) -> Result<()> {
586 let mut db = setup(t).await;
587
588 {
589 let mut tx = db.transaction_builder().begin().await?;
590 User::create().name("Ghost").exec(&mut tx).await?;
591 }
592
593 let users = User::all().exec(&mut db).await?;
594 assert!(users.is_empty());
595
596 Ok(())
597}
598
599#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
601pub async fn transaction_via_dyn_executor(t: &mut Test) -> Result<()> {
602 let mut db = setup(t).await;
603
604 let executor: &mut dyn toasty::Executor = &mut db;
605 let mut tx = executor.transaction().await?;
606 User::create().name("Alice").exec(&mut tx).await?;
607 tx.commit().await?;
608
609 let users = User::all().exec(&mut db).await?;
610 assert_eq!(users.len(), 1);
611 assert_eq!(users[0].name, "Alice");
612
613 Ok(())
614}