1use crate::prelude::*;
2
3#[driver_test(scenario(crate::scenarios::two_models), requires(scan))]
4pub async fn query_macro_scan_filters(test: &mut Test) -> Result<()> {
5 let mut db = setup(test).await;
6
7 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
8 .exec(&mut db)
9 .await?;
10
11 let users = toasty::query!(User).exec(&mut db).await?;
13 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }, { name: "Carl" }));
14
15 let users = toasty::query!(User filter .name == "Alice")
16 .exec(&mut db)
17 .await?;
18 assert_struct!(users, [{ name: "Alice" }]);
19
20 let users = toasty::query!(User filter .name != "Alice")
21 .exec(&mut db)
22 .await?;
23 assert_struct!(users, #({ name: "Bob" }, { name: "Carl" }));
24
25 let users = toasty::query!(User filter .name == "Alice" or .name == "Bob")
26 .exec(&mut db)
27 .await?;
28 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
29
30 let users = toasty::query!(User filter not .name == "Alice")
31 .exec(&mut db)
32 .await?;
33 assert_struct!(users, #({ name: "Bob" }, { name: "Carl" }));
34
35 let target_name = "Alice";
36 let users = toasty::query!(User filter .name == #target_name)
37 .exec(&mut db)
38 .await?;
39 assert_struct!(users, [{ name: "Alice" }]);
40
41 fn get_name() -> &'static str {
42 "Bob"
43 }
44 let users = toasty::query!(User filter .name == #(get_name()))
45 .exec(&mut db)
46 .await?;
47 assert_struct!(users, [{ name: "Bob" }]);
48
49 let users = toasty::query!(User FILTER .name == "Alice")
50 .exec(&mut db)
51 .await?;
52 assert_struct!(users, [{ name: "Alice" }]);
53
54 let users = toasty::query!(User Filter .name == "Alice" AND .name == "Alice")
55 .exec(&mut db)
56 .await?;
57 assert_struct!(users, [{ name: "Alice" }]);
58
59 let users = toasty::query!(User filter .name IN ["Alice", "Carl"])
60 .exec(&mut db)
61 .await?;
62 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
63
64 let names = vec!["Alice", "Bob"];
65 let users = toasty::query!(User filter .name IN #names)
66 .exec(&mut db)
67 .await?;
68 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
69
70 let users = toasty::query!(User filter .name IN ["Alice", "Bob", "Carl"] and .name != "Bob")
71 .exec(&mut db)
72 .await?;
73 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
74
75 Ok(())
76}
77
78#[driver_test(scenario(crate::scenarios::user_with_age), requires(scan))]
79pub async fn query_macro_numeric_and_boolean_filters(test: &mut Test) -> Result<()> {
80 let mut db = setup(test).await;
81
82 toasty::create!(User::[
83 { name: "Young", age: 15 },
84 { name: "Adult", age: 25 },
85 { name: "Senior", age: 65 },
86 { name: "Alice", age: 30 },
87 { name: "Bob", age: 30 },
88 { name: "Alice", age: 20 },
89 { name: "Carl", age: 40 },
90 { name: "Diana", age: 10 },
91 ])
92 .exec(&mut db)
93 .await?;
94
95 let users = toasty::query!(User filter .age > 20).exec(&mut db).await?;
97 assert_struct!(users, #(
98 { name: "Adult" },
99 { name: "Senior" },
100 { name: "Alice" },
101 { name: "Bob" },
102 { name: "Carl" },
103 ));
104
105 let users = toasty::query!(User filter .age >= 25).exec(&mut db).await?;
107 assert_struct!(users, #(
108 { name: "Adult" },
109 { name: "Senior" },
110 { name: "Alice" },
111 { name: "Bob" },
112 { name: "Carl" },
113 ));
114
115 let users = toasty::query!(User filter .age < 25).exec(&mut db).await?;
117 assert_struct!(users, #(
118 { name: "Young" },
119 { name: "Alice", age: 20 },
120 { name: "Diana" },
121 ));
122
123 let users = toasty::query!(User filter .age <= 25).exec(&mut db).await?;
125 assert_struct!(users, #(
126 { name: "Young" },
127 { name: "Adult" },
128 { name: "Alice", age: 20 },
129 { name: "Diana" },
130 ));
131
132 let users = toasty::query!(User filter .name == "Alice" and .age == 30)
133 .exec(&mut db)
134 .await?;
135 assert_struct!(users, [{ name: "Alice", age: 30 }]);
136
137 let users = toasty::query!(User filter .name == "Alice" and (.age > 25 or .age < 15))
140 .exec(&mut db)
141 .await?;
142 assert_struct!(users, [{ name: "Alice" }]);
143
144 let users =
146 toasty::query!(User filter not (.age < 18) and (.name == "Alice" or .name == "Carl"))
147 .exec(&mut db)
148 .await?;
149 assert_struct!(users, #(
150 { name: "Alice", age: 30 },
151 { name: "Alice", age: 20 },
152 { name: "Carl" },
153 ));
154
155 Ok(())
156}
157
158#[driver_test(scenario(crate::scenarios::widget_mixed_types))]
159pub async fn query_macro_filter_bool_literal(test: &mut Test) -> Result<()> {
160 let mut db = setup(test).await;
161
162 toasty::create!(Widget::[
163 { label: "on", count: 0, active: true, description: "" },
164 { label: "off", count: 0, active: false, description: "" },
165 ])
166 .exec(&mut db)
167 .await?;
168
169 let widgets = toasty::query!(Widget filter .active == true)
170 .exec(&mut db)
171 .await?;
172
173 assert_struct!(widgets, [{ label: "on" }]);
174
175 Ok(())
176}
177
178#[driver_test(scenario(crate::scenarios::two_models), requires(sql))]
181pub async fn query_macro_ordering_and_pagination(test: &mut Test) -> Result<()> {
182 let mut db = setup(test).await;
183
184 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }, { name: "Diana" }])
185 .exec(&mut db)
186 .await?;
187
188 let users = toasty::query!(User ORDER BY .name ASC)
189 .exec(&mut db)
190 .await?;
191 assert_struct!(users, [
192 { name: "Alice" },
193 { name: "Bob" },
194 { name: "Carl" },
195 { name: "Diana" },
196 ]);
197
198 let users = toasty::query!(User ORDER BY .name DESC)
199 .exec(&mut db)
200 .await?;
201 assert_struct!(users, [
202 { name: "Diana" },
203 { name: "Carl" },
204 { name: "Bob" },
205 { name: "Alice" },
206 ]);
207
208 let users = toasty::query!(User ORDER BY .name ASC LIMIT 2)
209 .exec(&mut db)
210 .await?;
211 assert_eq!(users.len(), 2);
212 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
213
214 let users = toasty::query!(User ORDER BY .name ASC OFFSET 1 LIMIT 2)
216 .exec(&mut db)
217 .await?;
218 assert_struct!(users, [{ name: "Bob" }, { name: "Carl" }]);
219
220 let n = 1;
221 let users = toasty::query!(User ORDER BY .name ASC LIMIT #n)
222 .exec(&mut db)
223 .await?;
224 assert_struct!(users, [{ name: "Alice" }]);
225
226 let users = toasty::query!(User order by .name asc limit 2)
227 .exec(&mut db)
228 .await?;
229 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
230
231 Ok(())
232}
233
234#[driver_test(scenario(crate::scenarios::user_with_age), requires(sql))]
235pub async fn query_macro_filter_with_order_by_and_limit(test: &mut Test) -> Result<()> {
236 let mut db = setup(test).await;
237
238 toasty::create!(User::[
239 { name: "Alice", age: 30 },
240 { name: "Bob", age: 25 },
241 { name: "Carl", age: 35 },
242 { name: "Diana", age: 20 },
243 ])
244 .exec(&mut db)
245 .await?;
246
247 let users = toasty::query!(User FILTER .age > 20 ORDER BY .name DESC LIMIT 2)
249 .exec(&mut db)
250 .await?;
251 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }]);
252
253 Ok(())
254}
255
256#[driver_test]
261pub async fn query_macro_partition_key_filters(test: &mut Test) -> Result<()> {
262 #[derive(Debug, toasty::Model)]
263 #[key(partition = league, local = name)]
264 struct Team {
265 league: String,
266
267 name: String,
268
269 founded: i64,
270 }
271
272 let mut db = test.setup_db(models!(Team)).await;
273
274 for (league, name, founded) in [
275 ("MLS", "Portland Timbers", 2009),
276 ("MLS", "Seattle Sounders FC", 2007),
277 ("EPL", "Arsenal", 1886),
278 ("EPL", "Chelsea", 1905),
279 ] {
280 toasty::create!(Team {
281 league: league,
282 name: name,
283 founded: founded
284 })
285 .exec(&mut db)
286 .await?;
287 }
288
289 let teams = toasty::query!(Team filter .league == "EPL")
291 .exec(&mut db)
292 .await?;
293
294 assert_struct!(teams, #({ name: "Arsenal" }, { name: "Chelsea" }));
295
296 let teams = toasty::query!(Team filter .league == "MLS" and .name == "Portland Timbers")
298 .exec(&mut db)
299 .await?;
300
301 assert_struct!(teams, [{ name: "Portland Timbers", founded: 2009 }]);
302
303 let target_league = "MLS";
304 let teams = toasty::query!(Team filter .league == #target_league)
305 .exec(&mut db)
306 .await?;
307 assert_struct!(teams, #({ name: "Portland Timbers" }, { name: "Seattle Sounders FC" }));
308
309 Ok(())
310}
311
312#[driver_test]
313pub async fn query_macro_local_key_comparison(test: &mut Test) -> Result<()> {
314 #[derive(Debug, toasty::Model)]
315 #[key(partition = kind, local = timestamp)]
316 struct Event {
317 kind: String,
318
319 timestamp: i64,
320 }
321
322 let mut db = test.setup_db(models!(Event)).await;
323
324 for (kind, ts) in [
325 ("info", 0),
326 ("info", 2),
327 ("info", 4),
328 ("info", 6),
329 ("info", 8),
330 ("info", 10),
331 ("warn", 1),
332 ("warn", 3),
333 ("warn", 5),
334 ] {
335 toasty::create!(Event {
336 kind: kind,
337 timestamp: ts
338 })
339 .exec(&mut db)
340 .await?;
341 }
342
343 let events = toasty::query!(Event filter .kind == "info" and .timestamp > 6)
345 .exec(&mut db)
346 .await?;
347
348 assert_struct!(events, #({ timestamp: 8 }, { timestamp: 10 }));
349
350 let events = toasty::query!(Event filter .kind == "info" and .timestamp <= 4)
352 .exec(&mut db)
353 .await?;
354
355 assert_struct!(events, #({ timestamp: 0 }, { timestamp: 2 }, { timestamp: 4 }));
356
357 Ok(())
358}
359
360#[driver_test]
361pub async fn query_macro_partition_key_with_not(test: &mut Test) -> Result<()> {
362 #[derive(Debug, toasty::Model)]
363 #[key(partition = team, local = name)]
364 struct Player {
365 team: String,
366
367 name: String,
368
369 position: String,
370 }
371
372 let mut db = test.setup_db(models!(Player)).await;
373
374 for (team, name, position) in [
375 ("Timbers", "Diego Valeri", "Midfielder"),
376 ("Timbers", "Fanendo Adi", "Forward"),
377 ("Timbers", "Adam Kwarasey", "Goalkeeper"),
378 ("Sounders", "Clint Dempsey", "Forward"),
379 ] {
380 toasty::create!(Player {
381 team: team,
382 name: name,
383 position: position
384 })
385 .exec(&mut db)
386 .await?;
387 }
388
389 let players =
391 toasty::query!(Player filter .team == "Timbers" and not .position == "Midfielder")
392 .exec(&mut db)
393 .await?;
394
395 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
396
397 Ok(())
398}
399
400#[driver_test]
401pub async fn query_macro_partition_key_with_or(test: &mut Test) -> Result<()> {
402 #[derive(Debug, toasty::Model)]
403 #[key(partition = team, local = name)]
404 struct Player {
405 team: String,
406
407 name: String,
408
409 position: String,
410
411 number: i64,
412 }
413
414 let mut db = test.setup_db(models!(Player)).await;
415
416 for (team, name, position, number) in [
417 ("Timbers", "Diego Valeri", "Midfielder", 8),
418 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
419 ("Timbers", "Fanendo Adi", "Forward", 9),
420 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
421 ("Sounders", "Clint Dempsey", "Forward", 2),
422 ] {
423 toasty::create!(Player {
424 team: team,
425 name: name,
426 position: position,
427 number: number
428 })
429 .exec(&mut db)
430 .await?;
431 }
432
433 let players = toasty::query!(Player filter .team == "Timbers" and (.position == "Forward" or .position == "Goalkeeper"))
435 .exec(&mut db)
436 .await?;
437
438 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
439
440 Ok(())
441}
442
443#[driver_test(scenario(crate::scenarios::two_models))]
444pub async fn query_macro_filter_in_list_by_pk(test: &mut Test) -> Result<()> {
445 let mut db = setup(test).await;
446
447 let mut ids = Vec::new();
449 for name in ["Alice", "Bob", "Carl", "Diana"] {
450 let user = User::create().name(name).exec(&mut db).await?;
451 ids.push(user.id);
452 }
453
454 let target_ids = vec![ids[0], ids[2]]; let users = toasty::query!(User filter .id IN #target_ids)
457 .exec(&mut db)
458 .await?;
459
460 assert_eq!(users.len(), 2);
461 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
462
463 Ok(())
464}