toasty_driver_integration_suite/tests/
crud_batch_create.rs1use crate::prelude::*;
4
5use toasty_core::driver::{Operation, operation::Transaction};
6
7#[driver_test(scenario(crate::scenarios::two_models))]
8pub async fn batch_create_empty(test: &mut Test) -> Result<()> {
9 let mut db = setup(test).await;
10
11 let res = Post::create_many().exec(&mut db).await?;
12 assert!(res.is_empty());
13 Ok(())
14}
15
16#[driver_test(scenario(crate::scenarios::two_models))]
17pub async fn batch_create_one(test: &mut Test) -> Result<()> {
18 let mut db = setup(test).await;
19
20 test.log().clear();
21 let res = Post::create_many()
22 .item(Post::create().title("hello"))
23 .exec(&mut db)
24 .await?;
25
26 assert_eq!(1, res.len());
27 assert_eq!(res[0].title, "hello");
28
29 if test.capability().sql() {
31 assert_struct!(test.log().pop_op(), Operation::Insert(_));
32 assert!(test.log().is_empty());
33 }
34
35 let reloaded: Vec<_> = Post::filter_by_id(res[0].id).exec(&mut db).await?;
36 assert_eq!(1, reloaded.len());
37 assert_eq!(reloaded[0].id, res[0].id);
38 Ok(())
39}
40
41#[driver_test(scenario(crate::scenarios::two_models))]
42pub async fn batch_create_many(test: &mut Test) -> Result<()> {
43 let mut db = setup(test).await;
44
45 test.log().clear();
46 let res = Post::create_many()
47 .item(Post::create().title("todo 1"))
48 .item(Post::create().title("todo 2"))
49 .exec(&mut db)
50 .await?;
51
52 assert_eq!(2, res.len());
53 assert_eq!(res[0].title, "todo 1");
54 assert_eq!(res[1].title, "todo 2");
55
56 if test.capability().sql() {
59 assert_struct!(test.log().pop_op(), Operation::Insert(_));
60 assert!(test.log().is_empty());
61 }
62
63 for post in &res {
64 let reloaded: Vec<_> = Post::filter_by_id(post.id).exec(&mut db).await?;
65 assert_eq!(1, reloaded.len());
66 assert_eq!(reloaded[0].id, post.id);
67 }
68 Ok(())
69}
70
71#[driver_test(requires(and(auto_increment, returning_from_mutation)))]
72pub async fn batch_create_many_auto_increment(test: &mut Test) -> Result<()> {
73 #[derive(Debug, toasty::Model)]
74 struct Item {
75 #[key]
76 #[auto]
77 id: u64,
78
79 name: String,
80 }
81
82 let mut db = test.setup_db(models!(Item)).await;
83 let items = Item::create_many()
84 .item(Item::create().name("one"))
85 .item(Item::create().name("two"))
86 .exec(&mut db)
87 .await?;
88
89 assert_struct!(items, [{ id: 1, name: "one" }, { id: 2, name: "two" }]);
90
91 Ok(())
92}
93
94#[driver_test(requires(and(auto_increment, not(returning_from_mutation))))]
95pub async fn batch_create_many_auto_increment_requires_returning(test: &mut Test) -> Result<()> {
96 #[derive(Debug, toasty::Model)]
97 struct Generated {
98 #[key]
99 #[auto]
100 id: u64,
101
102 name: String,
103 }
104
105 #[derive(Debug, toasty::Model)]
106 struct Manual {
107 #[key]
108 id: u64,
109
110 name: String,
111 }
112
113 let mut db = test.setup_db(models!(Generated, Manual)).await;
114
115 test.log().clear();
116 let err = assert_err!(
117 Generated::create_many()
118 .item(Generated::create().name("one"))
119 .item(Generated::create().name("two"))
120 .exec(&mut db)
121 .await
122 );
123
124 assert!(err.is_unsupported_feature());
125 assert!(err.to_string().contains(test.capability().driver_name));
126 assert!(err.to_string().contains("generateds.id"));
127 assert!(test.log().is_empty());
128
129 let items = Manual::create_many()
130 .item(Manual::create().id(10).name("one"))
131 .item(Manual::create().id(20).name("two"))
132 .exec(&mut db)
133 .await?;
134
135 assert_struct!(items, [{ id: 10, name: "one" }, { id: 20, name: "two" }]);
136 assert_struct!(test.log().pop_op(), Operation::Insert({ ret: None, .. }));
137 assert!(test.log().is_empty());
138
139 Ok(())
140}
141
142#[driver_test]
144#[should_panic]
145pub async fn batch_create_fails_if_any_record_missing_fields(test: &mut Test) -> Result<()> {
146 #[derive(Debug, toasty::Model)]
147 struct User {
148 #[key]
149 email: String,
150
151 #[allow(dead_code)]
152 name: String,
153 }
154
155 let mut db = test.setup_db(models!(User)).await;
156
157 let res = User::create_many()
158 .item(User::create().email("user1@example.com").name("User 1"))
159 .item(User::create().email("user2@example.com"))
160 .exec(&mut db)
161 .await?;
162
163 assert!(res.is_empty());
164
165 let users: Vec<_> = User::filter_by_email("me@carllerche.com")
166 .exec(&mut db)
167 .await?;
168
169 assert!(users.is_empty());
170 Ok(())
171}
172
173#[driver_test(scenario(crate::scenarios::user_unique_email))]
174pub async fn batch_create_model_with_unique_field_index_all_unique(test: &mut Test) -> Result<()> {
175 let mut db = setup(test).await;
176
177 let mut res = User::create_many()
178 .item(User::create().email("user1@example.com"))
179 .item(User::create().email("user2@example.com"))
180 .exec(&mut db)
181 .await?;
182
183 assert_eq!(2, res.len());
184
185 res.sort_by_key(|user| user.email.clone());
186
187 assert_eq!(res[0].email, "user1@example.com");
188 assert_eq!(res[1].email, "user2@example.com");
189
190 for user in &res {
192 let found = User::get_by_id(&mut db, user.id).await?;
193 assert_eq!(found.id, user.id);
194 assert_eq!(found.email, user.email);
195
196 let found = User::get_by_email(&mut db, &user.email).await?;
197 assert_eq!(found.id, user.id);
198 assert_eq!(found.email, user.email);
199 }
200 Ok(())
201}
202
203#[driver_test(scenario(crate::scenarios::user_unique_email))]
204#[should_panic]
205pub async fn batch_create_model_with_unique_field_index_all_dups(test: &mut Test) -> Result<()> {
206 let mut db = setup(test).await;
207
208 let _res = User::create_many()
209 .item(User::create().email("user@example.com"))
210 .item(User::create().email("user@example.com"))
211 .exec(&mut db)
212 .await?;
213 Ok(())
214}
215
216#[driver_test(requires(sql), scenario(crate::scenarios::user_unique_email))]
219pub async fn batch_create_unique_violation_rolls_back(t: &mut Test) -> Result<()> {
220 let mut db = setup(t).await;
221
222 User::create()
224 .email("taken@example.com")
225 .exec(&mut db)
226 .await?;
227
228 t.log().clear();
229 assert_err!(
230 User::create_many()
231 .item(User::create().email("new@example.com"))
232 .item(User::create().email("taken@example.com"))
233 .exec(&mut db)
234 .await
235 );
236
237 assert!(t.log().is_empty());
239
240 let users = User::all().exec(&mut db).await?;
242 assert_eq!(1, users.len());
243
244 Ok(())
245}
246
247#[driver_test(requires(sql), scenario(crate::scenarios::two_models))]
250pub async fn batch_create_inside_transaction_uses_savepoints(t: &mut Test) -> Result<()> {
251 let mut db = setup(t).await;
252
253 t.log().clear();
254 let mut tx = db.transaction().await?;
255
256 assert_struct!(
257 t.log().pop_op(),
258 Operation::Transaction(Transaction::Start {
259 isolation: None,
260 read_only: false,
261 ..
262 })
263 );
264
265 Post::create_many()
266 .item(Post::create().title("a"))
267 .item(Post::create().title("b"))
268 .exec(&mut tx)
269 .await?;
270
271 assert_struct!(t.log().pop_op(), Operation::Insert(_));
273
274 tx.commit().await?;
275
276 assert_struct!(
277 t.log().pop_op(),
278 Operation::Transaction(Transaction::Commit)
279 );
280 assert!(t.log().is_empty());
281
282 Ok(())
283}