toasty_driver_integration_suite/tests/
batch_associations.rs1use crate::prelude::*;
5
6#[driver_test(
8 requires(scan),
9 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
10)]
11pub async fn batch_two_scoped_creates_same_relation(t: &mut Test) -> Result<()> {
12 let mut db = setup(t).await;
13 let user = User::create().name("Alice").exec(&mut db).await?;
14
15 let (t1, t2): (Todo, Todo) = toasty::batch((
16 user.todos().create().title("first"),
17 user.todos().create().title("second"),
18 ))
19 .exec(&mut db)
20 .await?;
21
22 assert_eq!(t1.title, "first");
23 assert_eq!(t2.title, "second");
24 assert_eq!(t1.user_id, user.id);
25 assert_eq!(t2.user_id, user.id);
26
27 let all: Vec<Todo> = user.todos().exec(&mut db).await?;
28 assert_eq!(all.len(), 2);
29
30 Ok(())
31}
32
33#[driver_test(
35 requires(scan),
36 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
37)]
38pub async fn batch_two_scoped_queries_same_relation(t: &mut Test) -> Result<()> {
39 let mut db = setup(t).await;
40
41 let u1 = User::create().name("u1").exec(&mut db).await?;
42 let u2 = User::create().name("u2").exec(&mut db).await?;
43 u1.todos().create().title("u1 todo").exec(&mut db).await?;
44 u2.todos().create().title("u2 todo").exec(&mut db).await?;
45
46 let (u1_todos, u2_todos): (Vec<Todo>, Vec<Todo>) = toasty::batch((u1.todos(), u2.todos()))
47 .exec(&mut db)
48 .await?;
49
50 assert_struct!(u1_todos, [{ title: "u1 todo" }]);
51 assert_struct!(u2_todos, [{ title: "u2 todo" }]);
52
53 Ok(())
54}
55
56#[driver_test(
58 requires(scan),
59 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
60)]
61pub async fn batch_scoped_update_and_delete_same_relation(t: &mut Test) -> Result<()> {
62 let mut db = setup(t).await;
63 let user = User::create().name("Alice").exec(&mut db).await?;
64 let todo_keep = user.todos().create().title("keep").exec(&mut db).await?;
65 let todo_drop = user.todos().create().title("drop").exec(&mut db).await?;
66
67 let ((), ()): ((), ()) = toasty::batch((
68 user.todos()
69 .filter_by_id(todo_keep.id)
70 .update()
71 .title("kept"),
72 user.todos().filter_by_id(todo_drop.id).delete(),
73 ))
74 .exec(&mut db)
75 .await?;
76
77 let remaining: Vec<Todo> = user.todos().exec(&mut db).await?;
78 assert_eq!(remaining.len(), 1);
79 assert_eq!(remaining[0].title, "kept");
80
81 Ok(())
82}
83
84#[driver_test(
86 requires(scan),
87 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
88)]
89pub async fn batch_scoped_all_four_crud(t: &mut Test) -> Result<()> {
90 let mut db = setup(t).await;
91 let user = User::create().name("Alice").exec(&mut db).await?;
92 let existing = user
93 .todos()
94 .create()
95 .title("existing")
96 .exec(&mut db)
97 .await?;
98 let doomed = user.todos().create().title("doomed").exec(&mut db).await?;
99
100 let (queried, created, (), ()): (Vec<Todo>, Todo, (), ()) = toasty::batch((
101 user.todos(),
102 user.todos().create().title("new"),
103 user.todos()
104 .filter_by_id(existing.id)
105 .update()
106 .title("updated"),
107 user.todos().filter_by_id(doomed.id).delete(),
108 ))
109 .exec(&mut db)
110 .await?;
111
112 assert_eq!(queried.len(), 2);
114 assert_eq!(created.title, "new");
115
116 let final_todos: Vec<Todo> = user.todos().exec(&mut db).await?;
118 assert_eq!(final_todos.len(), 2); let titles: Vec<&str> = final_todos.iter().map(|t| t.title.as_str()).collect();
121 assert!(titles.contains(&"updated"));
122 assert!(titles.contains(&"new"));
123
124 Ok(())
125}
126
127#[driver_test(
129 requires(scan),
130 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
131)]
132pub async fn batch_scoped_with_root_statements(t: &mut Test) -> Result<()> {
133 let mut db = setup(t).await;
134 let user = User::create().name("Alice").exec(&mut db).await?;
135
136 let (users, todo, new_user): (Vec<User>, Todo, User) = toasty::batch((
138 User::filter_by_name("Alice"),
139 user.todos().create().title("from batch"),
140 User::create().name("Bob"),
141 ))
142 .exec(&mut db)
143 .await?;
144
145 assert_struct!(users, [{ name: "Alice" }]);
146 assert_eq!(todo.title, "from batch");
147 assert_eq!(todo.user_id, user.id);
148 assert_eq!(new_user.name, "Bob");
149
150 Ok(())
151}
152
153#[driver_test(requires(scan), scenario(crate::scenarios::user_two_children))]
155pub async fn batch_scoped_across_relations(t: &mut Test) -> Result<()> {
156 let mut db = setup(t).await;
157 let user = User::create().name("Alice").exec(&mut db).await?;
158
159 let (post, comment): (Post, Comment) = toasty::batch((
161 user.posts().create().title("my post"),
162 user.comments().create().text("my comment"),
163 ))
164 .exec(&mut db)
165 .await?;
166
167 assert_eq!(post.title, "my post");
168 assert_eq!(post.user_id, user.id);
169 assert_eq!(comment.text, "my comment");
170 assert_eq!(comment.user_id, user.id);
171
172 Ok(())
173}
174
175#[driver_test(requires(scan), scenario(crate::scenarios::user_two_children))]
177pub async fn batch_query_across_relations(t: &mut Test) -> Result<()> {
178 let mut db = setup(t).await;
179 let user = User::create().name("Alice").exec(&mut db).await?;
180 user.posts().create().title("t1").exec(&mut db).await?;
181 user.posts().create().title("t2").exec(&mut db).await?;
182 user.comments().create().text("p1").exec(&mut db).await?;
183
184 let (posts, comments): (Vec<Post>, Vec<Comment>) =
185 toasty::batch((user.posts(), user.comments()))
186 .exec(&mut db)
187 .await?;
188
189 assert_eq!(posts.len(), 2);
190 assert_eq!(comments.len(), 1);
191 assert_eq!(comments[0].text, "p1");
192
193 Ok(())
194}
195
196#[driver_test(
198 requires(scan),
199 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
200)]
201pub async fn batch_scoped_different_parents(t: &mut Test) -> Result<()> {
202 let mut db = setup(t).await;
203 let alice = User::create().name("Alice").exec(&mut db).await?;
204 let bob = User::create().name("Bob").exec(&mut db).await?;
205
206 let (alice_todo, bob_todo): (Todo, Todo) = toasty::batch((
208 alice.todos().create().title("alice task"),
209 bob.todos().create().title("bob task"),
210 ))
211 .exec(&mut db)
212 .await?;
213
214 assert_eq!(alice_todo.user_id, alice.id);
215 assert_eq!(bob_todo.user_id, bob.id);
216
217 let (alice_todos, bob_todos): (Vec<Todo>, Vec<Todo>) =
219 toasty::batch((alice.todos(), bob.todos()))
220 .exec(&mut db)
221 .await?;
222
223 assert_struct!(alice_todos, [{ title: "alice task" }]);
224 assert_struct!(bob_todos, [{ title: "bob task" }]);
225
226 Ok(())
227}
228
229#[driver_test(
231 requires(scan),
232 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
233)]
234pub async fn batch_scoped_delete_with_root_update(t: &mut Test) -> Result<()> {
235 let mut db = setup(t).await;
236 let user = User::create().name("Alice").exec(&mut db).await?;
237 let todo = user.todos().create().title("done").exec(&mut db).await?;
238
239 let ((), ()): ((), ()) = toasty::batch((
240 user.todos().filter_by_id(todo.id).delete(),
241 User::filter_by_name("Alice").update().name("Alice2"),
242 ))
243 .exec(&mut db)
244 .await?;
245
246 let remaining: Vec<Todo> = user.todos().exec(&mut db).await?;
248 assert!(remaining.is_empty());
249
250 let updated: Vec<User> = User::filter_by_name("Alice2").exec(&mut db).await?;
252 assert_eq!(updated.len(), 1);
253
254 Ok(())
255}