toasty_driver_integration_suite/tests/
crud_update_arithmetic.rs1use crate::prelude::*;
2
3use toasty_core::{
4 driver::Operation,
5 stmt::{Assignment, Statement, UpdateTarget},
6};
7
8#[driver_test(scenario(crate::scenarios::counter_value))]
9pub async fn increment_adds_one(t: &mut Test) -> Result<()> {
10 let mut db = setup(t).await;
11 let mut counter = toasty::create!(Counter {
12 id: uuid::Uuid::new_v4(),
13 value: 10,
14 })
15 .exec(&mut db)
16 .await?;
17
18 counter
19 .update()
20 .value(toasty::stmt::increment())
21 .exec(&mut db)
22 .await?;
23
24 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
25 assert_eq!(reloaded.value, 11);
26 Ok(())
27}
28
29#[driver_test(scenario(crate::scenarios::counter_value))]
30pub async fn decrement_subtracts_one(t: &mut Test) -> Result<()> {
31 let mut db = setup(t).await;
32 let mut counter = toasty::create!(Counter {
33 id: uuid::Uuid::new_v4(),
34 value: 10,
35 })
36 .exec(&mut db)
37 .await?;
38
39 counter
40 .update()
41 .value(toasty::stmt::decrement())
42 .exec(&mut db)
43 .await?;
44
45 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
46 assert_eq!(reloaded.value, 9);
47 Ok(())
48}
49
50#[driver_test(scenario(crate::scenarios::counter_value))]
51pub async fn add_adds_value(t: &mut Test) -> Result<()> {
52 let mut db = setup(t).await;
53 let mut counter = toasty::create!(Counter {
54 id: uuid::Uuid::new_v4(),
55 value: 10,
56 })
57 .exec(&mut db)
58 .await?;
59
60 counter
61 .update()
62 .value(toasty::stmt::add(25))
63 .exec(&mut db)
64 .await?;
65
66 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
67 assert_eq!(reloaded.value, 35);
68 Ok(())
69}
70
71#[driver_test(scenario(crate::scenarios::counter_value))]
72pub async fn subtract_subtracts_value(t: &mut Test) -> Result<()> {
73 let mut db = setup(t).await;
74 let mut counter = toasty::create!(Counter {
75 id: uuid::Uuid::new_v4(),
76 value: 10,
77 })
78 .exec(&mut db)
79 .await?;
80
81 counter
82 .update()
83 .value(toasty::stmt::subtract(3))
84 .exec(&mut db)
85 .await?;
86
87 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
88 assert_eq!(reloaded.value, 7);
89 Ok(())
90}
91
92#[driver_test(scenario(crate::scenarios::counter_value))]
93pub async fn add_negative_value(t: &mut Test) -> Result<()> {
94 let mut db = setup(t).await;
95 let mut counter = toasty::create!(Counter {
96 id: uuid::Uuid::new_v4(),
97 value: 10,
98 })
99 .exec(&mut db)
100 .await?;
101
102 counter
103 .update()
104 .value(toasty::stmt::add(-4))
105 .exec(&mut db)
106 .await?;
107
108 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
109 assert_eq!(reloaded.value, 6);
110 Ok(())
111}
112
113#[driver_test(scenario(crate::scenarios::counter_value))]
114pub async fn increment_emits_add_assignment(t: &mut Test) -> Result<()> {
115 let mut db = setup(t).await;
116 let mut counter = toasty::create!(Counter {
117 id: uuid::Uuid::new_v4(),
118 value: 10,
119 })
120 .exec(&mut db)
121 .await?;
122
123 let counter_table_id = table_id(&db, "counters");
124 let is_sql = t.capability().sql;
125
126 t.log().clear();
127 counter
128 .update()
129 .value(toasty::stmt::increment())
130 .exec(&mut db)
131 .await?;
132
133 let (op, _resp) = t.log().pop();
134 if is_sql {
139 assert_struct!(op, Operation::QuerySql({
140 stmt: Statement::Update({
141 target: UpdateTarget::Table(== counter_table_id),
142 assignments: #{ [1]: Assignment::Add(_) },
143 }),
144 ..
145 }));
146 } else {
147 assert_struct!(op, Operation::UpdateByKey({
148 table: == counter_table_id,
149 assignments: #{ [1]: Assignment::Add(_) },
150 ..
151 }));
152 }
153 Ok(())
154}
155
156#[driver_test]
157pub async fn arithmetic_chains_with_other_updates(t: &mut Test) -> Result<()> {
158 #[derive(Debug, toasty::Model)]
159 struct Profile {
160 #[key]
161 id: uuid::Uuid,
162
163 name: String,
164 login_count: i64,
165 }
166
167 let mut db = t.setup_db(models!(Profile)).await;
168 let mut profile = toasty::create!(Profile {
169 id: uuid::Uuid::new_v4(),
170 name: "alice",
171 login_count: 5,
172 })
173 .exec(&mut db)
174 .await?;
175
176 profile
177 .update()
178 .name("alice2")
179 .login_count(toasty::stmt::increment())
180 .exec(&mut db)
181 .await?;
182
183 let reloaded = Profile::get_by_id(&mut db, &profile.id).await?;
184 assert_struct!(reloaded, _ { name: "alice2", login_count: 6, .. });
185 Ok(())
186}
187
188#[driver_test(scenario(crate::scenarios::counter_value))]
189pub async fn multiple_add_on_one_field(t: &mut Test) -> Result<()> {
190 let mut db = setup(t).await;
196 let mut counter = toasty::create!(Counter {
197 id: uuid::Uuid::new_v4(),
198 value: 10,
199 })
200 .exec(&mut db)
201 .await?;
202
203 counter
204 .update()
205 .value(toasty::stmt::add(2))
206 .value(toasty::stmt::add(3))
207 .exec(&mut db)
208 .await?;
209
210 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
211 assert_eq!(reloaded.value, 15);
212 Ok(())
213}
214
215#[driver_test(scenario(crate::scenarios::counter_value))]
216pub async fn subtract_then_add_on_one_field(t: &mut Test) -> Result<()> {
217 let mut db = setup(t).await;
221 let mut counter = toasty::create!(Counter {
222 id: uuid::Uuid::new_v4(),
223 value: 10,
224 })
225 .exec(&mut db)
226 .await?;
227
228 counter
229 .update()
230 .value(toasty::stmt::subtract(3))
231 .value(toasty::stmt::add(7))
232 .exec(&mut db)
233 .await?;
234
235 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
236 assert_eq!(reloaded.value, 14);
237 Ok(())
238}
239
240#[driver_test(scenario(crate::scenarios::counter_value))]
241pub async fn set_then_arithmetic_on_one_field(t: &mut Test) -> Result<()> {
242 let mut db = setup(t).await;
246 let mut counter = toasty::create!(Counter {
247 id: uuid::Uuid::new_v4(),
248 value: 10,
249 })
250 .exec(&mut db)
251 .await?;
252
253 counter
254 .update()
255 .value(50)
256 .value(toasty::stmt::add(8))
257 .value(toasty::stmt::subtract(3))
258 .exec(&mut db)
259 .await?;
260
261 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
262 assert_eq!(reloaded.value, 55);
263 Ok(())
264}
265
266#[driver_test]
267pub async fn increment_unique_column(t: &mut Test) -> Result<()> {
268 #[derive(Debug, toasty::Model)]
274 struct Slot {
275 #[key]
276 id: uuid::Uuid,
277
278 #[unique]
279 count: i64,
280 }
281
282 let mut db = t.setup_db(models!(Slot)).await;
283 let mut slot = toasty::create!(Slot {
284 id: uuid::Uuid::new_v4(),
285 count: 10,
286 })
287 .exec(&mut db)
288 .await?;
289
290 slot.update()
291 .count(toasty::stmt::increment())
292 .exec(&mut db)
293 .await?;
294
295 let reloaded = Slot::get_by_id(&mut db, &slot.id).await?;
296 assert_eq!(reloaded.count, 11);
297 Ok(())
298}
299
300#[driver_test]
301pub async fn increment_narrow_integer_column(t: &mut Test) -> Result<()> {
302 #[derive(Debug, toasty::Model)]
308 struct Tally {
309 #[key]
310 id: uuid::Uuid,
311
312 count: i16,
313 }
314
315 let mut db = t.setup_db(models!(Tally)).await;
316 let mut tally = toasty::create!(Tally {
317 id: uuid::Uuid::new_v4(),
318 count: 10_i16,
319 })
320 .exec(&mut db)
321 .await?;
322
323 tally
324 .update()
325 .count(toasty::stmt::increment())
326 .exec(&mut db)
327 .await?;
328 assert_eq!(Tally::get_by_id(&mut db, &tally.id).await?.count, 11);
329
330 tally
331 .update()
332 .count(toasty::stmt::decrement())
333 .exec(&mut db)
334 .await?;
335 assert_eq!(Tally::get_by_id(&mut db, &tally.id).await?.count, 10);
336
337 Ok(())
338}
339
340#[driver_test(scenario(crate::scenarios::counter_value))]
341pub async fn filter_update_with_arithmetic(t: &mut Test) -> Result<()> {
342 let mut db = setup(t).await;
343 let counter = toasty::create!(Counter {
344 id: uuid::Uuid::new_v4(),
345 value: 10,
346 })
347 .exec(&mut db)
348 .await?;
349
350 Counter::filter_by_id(counter.id)
351 .update()
352 .value(toasty::stmt::add(100))
353 .exec(&mut db)
354 .await?;
355
356 let reloaded = Counter::get_by_id(&mut db, &counter.id).await?;
357 assert_eq!(reloaded.value, 110);
358 Ok(())
359}