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