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