toasty_driver_integration_suite/tests/
batch_associations.rs1use crate::prelude::*;
5
6#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
8pub async fn batch_two_scoped_creates_same_relation(t: &mut Test) -> Result<()> {
9 let mut db = setup(t).await;
10 let user = User::create().name("Alice").exec(&mut db).await?;
11
12 let (t1, t2): (Todo, Todo) = toasty::batch((
13 user.todos().create().title("first"),
14 user.todos().create().title("second"),
15 ))
16 .exec(&mut db)
17 .await?;
18
19 assert_eq!(t1.title, "first");
20 assert_eq!(t2.title, "second");
21 assert_eq!(t1.user_id, user.id);
22 assert_eq!(t2.user_id, user.id);
23
24 let all: Vec<Todo> = user.todos().exec(&mut db).await?;
25 assert_eq!(all.len(), 2);
26
27 Ok(())
28}
29
30#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
32pub async fn batch_two_scoped_queries_same_relation(t: &mut Test) -> Result<()> {
33 let mut db = setup(t).await;
34
35 let u1 = User::create().name("u1").exec(&mut db).await?;
36 let u2 = User::create().name("u2").exec(&mut db).await?;
37 u1.todos().create().title("u1 todo").exec(&mut db).await?;
38 u2.todos().create().title("u2 todo").exec(&mut db).await?;
39
40 let (u1_todos, u2_todos): (Vec<Todo>, Vec<Todo>) = toasty::batch((u1.todos(), u2.todos()))
41 .exec(&mut db)
42 .await?;
43
44 assert_struct!(u1_todos, [{ title: "u1 todo" }]);
45 assert_struct!(u2_todos, [{ title: "u2 todo" }]);
46
47 Ok(())
48}
49
50#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
52pub async fn batch_scoped_update_and_delete_same_relation(t: &mut Test) -> Result<()> {
53 let mut db = setup(t).await;
54 let user = User::create().name("Alice").exec(&mut db).await?;
55 let todo_keep = user.todos().create().title("keep").exec(&mut db).await?;
56 let todo_drop = user.todos().create().title("drop").exec(&mut db).await?;
57
58 let ((), ()): ((), ()) = toasty::batch((
59 user.todos()
60 .filter_by_id(todo_keep.id)
61 .update()
62 .title("kept"),
63 user.todos().filter_by_id(todo_drop.id).delete(),
64 ))
65 .exec(&mut db)
66 .await?;
67
68 let remaining: Vec<Todo> = user.todos().exec(&mut db).await?;
69 assert_eq!(remaining.len(), 1);
70 assert_eq!(remaining[0].title, "kept");
71
72 Ok(())
73}
74
75#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
77pub async fn batch_scoped_all_four_crud(t: &mut Test) -> Result<()> {
78 let mut db = setup(t).await;
79 let user = User::create().name("Alice").exec(&mut db).await?;
80 let existing = user
81 .todos()
82 .create()
83 .title("existing")
84 .exec(&mut db)
85 .await?;
86 let doomed = user.todos().create().title("doomed").exec(&mut db).await?;
87
88 let (queried, created, (), ()): (Vec<Todo>, Todo, (), ()) = toasty::batch((
89 user.todos(),
90 user.todos().create().title("new"),
91 user.todos()
92 .filter_by_id(existing.id)
93 .update()
94 .title("updated"),
95 user.todos().filter_by_id(doomed.id).delete(),
96 ))
97 .exec(&mut db)
98 .await?;
99
100 assert_eq!(queried.len(), 2);
102 assert_eq!(created.title, "new");
103
104 let final_todos: Vec<Todo> = user.todos().exec(&mut db).await?;
106 assert_eq!(final_todos.len(), 2); let titles: Vec<&str> = final_todos.iter().map(|t| t.title.as_str()).collect();
109 assert!(titles.contains(&"updated"));
110 assert!(titles.contains(&"new"));
111
112 Ok(())
113}
114
115#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
117pub async fn batch_scoped_with_root_statements(t: &mut Test) -> Result<()> {
118 let mut db = setup(t).await;
119 let user = User::create().name("Alice").exec(&mut db).await?;
120
121 let (users, todo, new_user): (Vec<User>, Todo, User) = toasty::batch((
123 User::filter_by_name("Alice"),
124 user.todos().create().title("from batch"),
125 User::create().name("Bob"),
126 ))
127 .exec(&mut db)
128 .await?;
129
130 assert_struct!(users, [{ name: "Alice" }]);
131 assert_eq!(todo.title, "from batch");
132 assert_eq!(todo.user_id, user.id);
133 assert_eq!(new_user.name, "Bob");
134
135 Ok(())
136}
137
138#[driver_test(id(ID), requires(sql))]
140pub async fn batch_scoped_across_relations(t: &mut Test) -> Result<()> {
141 #[derive(Debug, toasty::Model)]
142 struct User {
143 #[key]
144 #[auto]
145 id: ID,
146 #[has_many]
147 todos: toasty::HasMany<Todo>,
148 #[has_many]
149 posts: toasty::HasMany<Post>,
150 }
151
152 #[derive(Debug, toasty::Model)]
153 struct Todo {
154 #[key]
155 #[auto]
156 id: ID,
157 #[index]
158 user_id: ID,
159 #[belongs_to(key = user_id, references = id)]
160 user: toasty::BelongsTo<User>,
161 title: String,
162 }
163
164 #[derive(Debug, toasty::Model)]
165 struct Post {
166 #[key]
167 #[auto]
168 id: ID,
169 #[index]
170 user_id: ID,
171 #[belongs_to(key = user_id, references = id)]
172 user: toasty::BelongsTo<User>,
173 body: String,
174 }
175
176 let mut db = t.setup_db(models!(User, Todo, Post)).await;
177 let user = User::create().exec(&mut db).await?;
178
179 let (todo, post): (Todo, Post) = toasty::batch((
181 user.todos().create().title("my todo"),
182 user.posts().create().body("my post"),
183 ))
184 .exec(&mut db)
185 .await?;
186
187 assert_eq!(todo.title, "my todo");
188 assert_eq!(todo.user_id, user.id);
189 assert_eq!(post.body, "my post");
190 assert_eq!(post.user_id, user.id);
191
192 Ok(())
193}
194
195#[driver_test(id(ID), requires(sql))]
197pub async fn batch_query_across_relations(t: &mut Test) -> Result<()> {
198 #[derive(Debug, toasty::Model)]
199 struct User {
200 #[key]
201 #[auto]
202 id: ID,
203 #[has_many]
204 todos: toasty::HasMany<Todo>,
205 #[has_many]
206 posts: toasty::HasMany<Post>,
207 }
208
209 #[derive(Debug, toasty::Model)]
210 struct Todo {
211 #[key]
212 #[auto]
213 id: ID,
214 #[index]
215 user_id: ID,
216 #[belongs_to(key = user_id, references = id)]
217 user: toasty::BelongsTo<User>,
218 title: String,
219 }
220
221 #[derive(Debug, toasty::Model)]
222 struct Post {
223 #[key]
224 #[auto]
225 id: ID,
226 #[index]
227 user_id: ID,
228 #[belongs_to(key = user_id, references = id)]
229 user: toasty::BelongsTo<User>,
230 body: String,
231 }
232
233 let mut db = t.setup_db(models!(User, Todo, Post)).await;
234 let user = User::create().exec(&mut db).await?;
235 user.todos().create().title("t1").exec(&mut db).await?;
236 user.todos().create().title("t2").exec(&mut db).await?;
237 user.posts().create().body("p1").exec(&mut db).await?;
238
239 let (todos, posts): (Vec<Todo>, Vec<Post>) = toasty::batch((user.todos(), user.posts()))
240 .exec(&mut db)
241 .await?;
242
243 assert_eq!(todos.len(), 2);
244 assert_eq!(posts.len(), 1);
245 assert_eq!(posts[0].body, "p1");
246
247 Ok(())
248}
249
250#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
252pub async fn batch_scoped_different_parents(t: &mut Test) -> Result<()> {
253 let mut db = setup(t).await;
254 let alice = User::create().name("Alice").exec(&mut db).await?;
255 let bob = User::create().name("Bob").exec(&mut db).await?;
256
257 let (alice_todo, bob_todo): (Todo, Todo) = toasty::batch((
259 alice.todos().create().title("alice task"),
260 bob.todos().create().title("bob task"),
261 ))
262 .exec(&mut db)
263 .await?;
264
265 assert_eq!(alice_todo.user_id, alice.id);
266 assert_eq!(bob_todo.user_id, bob.id);
267
268 let (alice_todos, bob_todos): (Vec<Todo>, Vec<Todo>) =
270 toasty::batch((alice.todos(), bob.todos()))
271 .exec(&mut db)
272 .await?;
273
274 assert_struct!(alice_todos, [{ title: "alice task" }]);
275 assert_struct!(bob_todos, [{ title: "bob task" }]);
276
277 Ok(())
278}
279
280#[driver_test(id(ID), requires(sql), scenario(crate::scenarios::has_many_belongs_to))]
282pub async fn batch_scoped_delete_with_root_update(t: &mut Test) -> Result<()> {
283 let mut db = setup(t).await;
284 let user = User::create().name("Alice").exec(&mut db).await?;
285 let todo = user.todos().create().title("done").exec(&mut db).await?;
286
287 let ((), ()): ((), ()) = toasty::batch((
288 user.todos().filter_by_id(todo.id).delete(),
289 User::filter_by_name("Alice").update().name("Alice2"),
290 ))
291 .exec(&mut db)
292 .await?;
293
294 let remaining: Vec<Todo> = user.todos().exec(&mut db).await?;
296 assert!(remaining.is_empty());
297
298 let updated: Vec<User> = User::filter_by_name("Alice2").exec(&mut db).await?;
300 assert_eq!(updated.len(), 1);
301
302 Ok(())
303}