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 );
162 assert_struct!(t.log().pop_op(), Operation::QuerySql(_)); assert_struct!(
164 t.log().pop_op(),
165 Operation::Transaction(Transaction::Commit)
166 );
167 assert!(t.log().is_empty());
168
169 Ok(())
170}
171
172#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
174pub async fn driver_sees_begin_rollback(t: &mut Test) -> Result<()> {
175 let mut db = setup(t).await;
176
177 t.log().clear();
178
179 let mut tx = db.transaction().await?;
180 User::create().name("Alice").exec(&mut tx).await?;
181 tx.rollback().await?;
182
183 assert_struct!(
184 t.log().pop_op(),
185 Operation::Transaction(Transaction::Start {
186 isolation: None,
187 read_only: false,
188 ..
189 })
190 );
191 assert_struct!(t.log().pop_op(), Operation::QuerySql(_)); assert_struct!(
193 t.log().pop_op(),
194 Operation::Transaction(Transaction::Rollback)
195 );
196 assert!(t.log().is_empty());
197
198 Ok(())
199}
200
201#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
206pub async fn nested_commit_both(t: &mut Test) -> Result<()> {
207 let mut db = setup(t).await;
208
209 let mut tx = db.transaction().await?;
210 User::create().name("Alice").exec(&mut tx).await?;
211
212 {
213 let mut nested = tx.transaction().await?;
214 User::create().name("Bob").exec(&mut nested).await?;
215 nested.commit().await?;
216 }
217
218 tx.commit().await?;
219
220 let users = User::all().exec(&mut db).await?;
221 assert_eq!(users.len(), 2);
222
223 Ok(())
224}
225
226#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
229pub async fn nested_rollback_inner(t: &mut Test) -> Result<()> {
230 let mut db = setup(t).await;
231
232 let mut tx = db.transaction().await?;
233 User::create().name("Alice").exec(&mut tx).await?;
234
235 {
236 let mut nested = tx.transaction().await?;
237 User::create().name("Ghost").exec(&mut nested).await?;
238 nested.rollback().await?;
239 }
240
241 tx.commit().await?;
242
243 let users = User::all().exec(&mut db).await?;
244 assert_eq!(users.len(), 1);
245 assert_eq!(users[0].name, "Alice");
246
247 Ok(())
248}
249
250#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
253pub async fn nested_rollback_outer(t: &mut Test) -> Result<()> {
254 let mut db = setup(t).await;
255
256 let mut tx = db.transaction().await?;
257 User::create().name("Alice").exec(&mut tx).await?;
258
259 {
260 let mut nested = tx.transaction().await?;
261 User::create().name("Bob").exec(&mut nested).await?;
262 nested.commit().await?;
263 }
264
265 tx.rollback().await?;
266
267 let users = User::all().exec(&mut db).await?;
268 assert!(users.is_empty());
269
270 Ok(())
271}
272
273#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
276pub async fn nested_drop_rolls_back_savepoint(t: &mut Test) -> Result<()> {
277 let mut db = setup(t).await;
278
279 let mut tx = db.transaction().await?;
280 User::create().name("Alice").exec(&mut tx).await?;
281
282 {
283 let mut nested = tx.transaction().await?;
284 User::create().name("Ghost").exec(&mut nested).await?;
285 }
287
288 tx.commit().await?;
289
290 let users = User::all().exec(&mut db).await?;
291 assert_eq!(users.len(), 1);
292 assert_eq!(users[0].name, "Alice");
293
294 Ok(())
295}
296
297#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
300pub async fn nested_driver_sees_savepoint_ops(t: &mut Test) -> Result<()> {
301 let mut db = setup(t).await;
302
303 t.log().clear();
304
305 let mut tx = db.transaction().await?;
306 User::create().name("Alice").exec(&mut tx).await?;
307
308 let mut nested = tx.transaction().await?;
309 User::create().name("Bob").exec(&mut nested).await?;
310 nested.commit().await?;
311
312 tx.commit().await?;
313
314 assert_struct!(
316 t.log().pop_op(),
317 Operation::Transaction(Transaction::Start {
318 isolation: None,
319 read_only: false,
320 ..
321 })
322 );
323 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
325 assert_struct!(
327 t.log().pop_op(),
328 Operation::Transaction(Transaction::Savepoint(_))
329 );
330 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
332 assert_struct!(
334 t.log().pop_op(),
335 Operation::Transaction(Transaction::ReleaseSavepoint(_))
336 );
337 assert_struct!(
339 t.log().pop_op(),
340 Operation::Transaction(Transaction::Commit)
341 );
342 assert!(t.log().is_empty());
343
344 Ok(())
345}
346
347#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
350pub async fn nested_driver_sees_rollback_to_savepoint(t: &mut Test) -> Result<()> {
351 let mut db = setup(t).await;
352
353 t.log().clear();
354
355 let mut tx = db.transaction().await?;
356
357 let mut nested = tx.transaction().await?;
358 User::create().name("Ghost").exec(&mut nested).await?;
359 nested.rollback().await?;
360
361 tx.commit().await?;
362
363 assert_struct!(
365 t.log().pop_op(),
366 Operation::Transaction(Transaction::Start {
367 isolation: None,
368 read_only: false,
369 ..
370 })
371 );
372 assert_struct!(
374 t.log().pop_op(),
375 Operation::Transaction(Transaction::Savepoint(_))
376 );
377 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
379 assert_struct!(
381 t.log().pop_op(),
382 Operation::Transaction(Transaction::RollbackToSavepoint(_))
383 );
384 assert_struct!(
386 t.log().pop_op(),
387 Operation::Transaction(Transaction::Commit)
388 );
389 assert!(t.log().is_empty());
390
391 Ok(())
392}
393
394#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
397pub async fn two_sequential_nested_transactions(t: &mut Test) -> Result<()> {
398 let mut db = setup(t).await;
399
400 let mut tx = db.transaction().await?;
401
402 {
403 let mut nested1 = tx.transaction().await?;
404 User::create().name("Alice").exec(&mut nested1).await?;
405 nested1.commit().await?;
406 }
407
408 {
409 let mut nested2 = tx.transaction().await?;
410 User::create().name("Ghost").exec(&mut nested2).await?;
411 nested2.rollback().await?;
412 }
413
414 tx.commit().await?;
415
416 let users = User::all().exec(&mut db).await?;
417 assert_eq!(users.len(), 1);
418 assert_eq!(users[0].name, "Alice");
419
420 Ok(())
421}
422
423#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
429pub async fn multi_op_inside_tx_uses_savepoints(t: &mut Test) -> Result<()> {
430 let mut db = setup(t).await;
431
432 t.log().clear();
433
434 let mut tx = db.transaction().await?;
435 let user = User::create()
436 .name("Alice")
437 .todo(Todo::create().title("task"))
438 .exec(&mut tx)
439 .await?;
440 tx.commit().await?;
441
442 assert_struct!(
444 t.log().pop_op(),
445 Operation::Transaction(Transaction::Start {
446 isolation: None,
447 read_only: false,
448 ..
449 })
450 );
451 assert_struct!(
453 t.log().pop_op(),
454 Operation::Transaction(Transaction::Savepoint(_))
455 );
456 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
458 assert_struct!(t.log().pop_op(), Operation::QuerySql(_));
460 assert_struct!(
462 t.log().pop_op(),
463 Operation::Transaction(Transaction::ReleaseSavepoint(_))
464 );
465 assert_struct!(
467 t.log().pop_op(),
468 Operation::Transaction(Transaction::Commit)
469 );
470 assert!(t.log().is_empty());
471
472 let todos = user.todos().exec(&mut db).await?;
474 assert_eq!(todos.len(), 1);
475 assert_eq!(todos[0].title, "task");
476
477 Ok(())
478}
479
480#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
484pub async fn builder_on_db_commit(t: &mut Test) -> Result<()> {
485 let mut db = setup(t).await;
486
487 let mut tx = db.transaction_builder().begin().await?;
488 User::create().name("Alice").exec(&mut tx).await?;
489 tx.commit().await?;
490
491 let users = User::all().exec(&mut db).await?;
492 assert_eq!(users.len(), 1);
493 assert_eq!(users[0].name, "Alice");
494
495 Ok(())
496}
497
498#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
500pub async fn builder_on_connection_commit(t: &mut Test) -> Result<()> {
501 let db = setup(t).await;
502 let mut conn = db.connection().await?;
503
504 let mut tx = conn.transaction_builder().begin().await?;
505 User::create().name("Alice").exec(&mut tx).await?;
506 tx.commit().await?;
507
508 let users = User::all().exec(&mut conn).await?;
509 assert_eq!(users.len(), 1);
510 assert_eq!(users[0].name, "Alice");
511
512 Ok(())
513}
514
515#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
517pub async fn builder_with_isolation_level(t: &mut Test) -> Result<()> {
518 let mut db = setup(t).await;
519
520 t.log().clear();
521
522 let mut tx = db
523 .transaction_builder()
524 .isolation(IsolationLevel::Serializable)
525 .begin()
526 .await?;
527 User::create().name("Alice").exec(&mut tx).await?;
528 tx.commit().await?;
529
530 assert_struct!(
531 t.log().pop_op(),
532 Operation::Transaction(Transaction::Start {
533 isolation: Some(IsolationLevel::Serializable),
534 read_only: false,
535 ..
536 })
537 );
538
539 Ok(())
540}
541
542#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
544pub async fn builder_with_read_only(t: &mut Test) -> Result<()> {
545 let mut db = setup(t).await;
546
547 t.log().clear();
548
549 let tx = db.transaction_builder().read_only(true).begin().await?;
550 tx.commit().await?;
551
552 assert_struct!(
553 t.log().pop_op(),
554 Operation::Transaction(Transaction::Start {
555 isolation: None,
556 read_only: true,
557 ..
558 })
559 );
560
561 Ok(())
562}
563
564#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
566pub async fn builder_with_all_options(t: &mut Test) -> Result<()> {
567 let mut db = setup(t).await;
568
569 t.log().clear();
570
571 let tx = db
572 .transaction_builder()
573 .isolation(IsolationLevel::Serializable)
574 .read_only(true)
575 .begin()
576 .await?;
577 tx.commit().await?;
578
579 assert_struct!(
580 t.log().pop_op(),
581 Operation::Transaction(Transaction::Start {
582 isolation: Some(IsolationLevel::Serializable),
583 read_only: true,
584 ..
585 })
586 );
587
588 Ok(())
589}
590
591#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
593pub async fn builder_drop_rolls_back(t: &mut Test) -> Result<()> {
594 let mut db = setup(t).await;
595
596 {
597 let mut tx = db.transaction_builder().begin().await?;
598 User::create().name("Ghost").exec(&mut tx).await?;
599 }
600
601 let users = User::all().exec(&mut db).await?;
602 assert!(users.is_empty());
603
604 Ok(())
605}
606
607#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::two_models))]
609pub async fn transaction_via_dyn_executor(t: &mut Test) -> Result<()> {
610 let mut db = setup(t).await;
611
612 let executor: &mut dyn toasty::Executor = &mut db;
613 let mut tx = executor.transaction().await?;
614 User::create().name("Alice").exec(&mut tx).await?;
615 tx.commit().await?;
616
617 let users = User::all().exec(&mut db).await?;
618 assert_eq!(users.len(), 1);
619 assert_eq!(users[0].name, "Alice");
620
621 Ok(())
622}