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