1use crate::prelude::*;
2
3#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
4pub async fn query_macro_all(test: &mut Test) -> Result<()> {
5 let mut db = setup(test).await;
6
7 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
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" }));
14
15 Ok(())
16}
17
18#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
19pub async fn query_macro_filter_eq(test: &mut Test) -> Result<()> {
20 let mut db = setup(test).await;
21
22 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
23 .exec(&mut db)
24 .await?;
25
26 let users = toasty::query!(User filter .name == "Alice")
28 .exec(&mut db)
29 .await?;
30
31 assert_struct!(users, [{ name: "Alice" }]);
32
33 Ok(())
34}
35
36#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
37pub async fn query_macro_filter_ne(test: &mut Test) -> Result<()> {
38 let mut db = setup(test).await;
39
40 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
41 .exec(&mut db)
42 .await?;
43
44 let users = toasty::query!(User filter .name != "Alice")
45 .exec(&mut db)
46 .await?;
47
48 assert_struct!(users, [{ name: "Bob" }]);
49
50 Ok(())
51}
52
53#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(scan))]
54pub async fn query_macro_filter_numeric_comparisons(test: &mut Test) -> Result<()> {
55 let mut db = setup(test).await;
56
57 toasty::create!(User::[
58 { name: "Young", age: 15 },
59 { name: "Adult", age: 25 },
60 { name: "Senior", age: 65 },
61 ])
62 .exec(&mut db)
63 .await?;
64
65 let users = toasty::query!(User filter .age > 20).exec(&mut db).await?;
67 assert_struct!(users, #({ name: "Adult" }, { name: "Senior" }));
68
69 let users = toasty::query!(User filter .age >= 25).exec(&mut db).await?;
71 assert_struct!(users, #({ name: "Adult" }, { name: "Senior" }));
72
73 let users = toasty::query!(User filter .age < 25).exec(&mut db).await?;
75 assert_struct!(users, [{ name: "Young" }]);
76
77 let users = toasty::query!(User filter .age <= 25).exec(&mut db).await?;
79 assert_struct!(users, #({ name: "Young" }, { name: "Adult" }));
80
81 Ok(())
82}
83
84#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(scan))]
85pub async fn query_macro_filter_and(test: &mut Test) -> Result<()> {
86 let mut db = setup(test).await;
87
88 toasty::create!(User::[
89 { name: "Alice", age: 30 },
90 { name: "Bob", age: 30 },
91 { name: "Alice", age: 20 },
92 ])
93 .exec(&mut db)
94 .await?;
95
96 let users = toasty::query!(User filter .name == "Alice" and .age == 30)
97 .exec(&mut db)
98 .await?;
99
100 assert_struct!(users, [{ name: "Alice", age: 30 }]);
101
102 Ok(())
103}
104
105#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
106pub async fn query_macro_filter_or(test: &mut Test) -> Result<()> {
107 let mut db = setup(test).await;
108
109 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
110 .exec(&mut db)
111 .await?;
112
113 let users = toasty::query!(User filter .name == "Alice" or .name == "Bob")
114 .exec(&mut db)
115 .await?;
116
117 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
118
119 Ok(())
120}
121
122#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
123pub async fn query_macro_filter_not(test: &mut Test) -> Result<()> {
124 let mut db = setup(test).await;
125
126 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
127 .exec(&mut db)
128 .await?;
129
130 let users = toasty::query!(User filter not .name == "Alice")
131 .exec(&mut db)
132 .await?;
133
134 assert_struct!(users, [{ name: "Bob" }]);
135
136 Ok(())
137}
138
139#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(scan))]
140pub async fn query_macro_filter_parens(test: &mut Test) -> Result<()> {
141 let mut db = setup(test).await;
142
143 toasty::create!(User::[
144 { name: "Alice", age: 30 },
145 { name: "Bob", age: 20 },
146 { name: "Carl", age: 40 },
147 ])
148 .exec(&mut db)
149 .await?;
150
151 let users = toasty::query!(User filter .name == "Alice" and (.age > 25 or .age < 15))
154 .exec(&mut db)
155 .await?;
156
157 assert_struct!(users, [{ name: "Alice" }]);
158
159 Ok(())
160}
161
162#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
163pub async fn query_macro_filter_external_ref(test: &mut Test) -> Result<()> {
164 let mut db = setup(test).await;
165
166 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
167 .exec(&mut db)
168 .await?;
169
170 let target_name = "Alice";
171 let users = toasty::query!(User filter .name == #target_name)
172 .exec(&mut db)
173 .await?;
174
175 assert_struct!(users, [{ name: "Alice" }]);
176
177 Ok(())
178}
179
180#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
181pub async fn query_macro_filter_external_expr(test: &mut Test) -> Result<()> {
182 let mut db = setup(test).await;
183
184 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
185 .exec(&mut db)
186 .await?;
187
188 fn get_name() -> &'static str {
189 "Bob"
190 }
191
192 let users = toasty::query!(User filter .name == #(get_name()))
193 .exec(&mut db)
194 .await?;
195
196 assert_struct!(users, [{ name: "Bob" }]);
197
198 Ok(())
199}
200
201#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
202pub async fn query_macro_case_insensitive_keywords(test: &mut Test) -> Result<()> {
203 let mut db = setup(test).await;
204
205 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
206 .exec(&mut db)
207 .await?;
208
209 let users = toasty::query!(User FILTER .name == "Alice")
211 .exec(&mut db)
212 .await?;
213 assert_struct!(users, [{ name: "Alice" }]);
214
215 let users = toasty::query!(User Filter .name == "Alice" AND .name == "Alice")
217 .exec(&mut db)
218 .await?;
219 assert_struct!(users, [{ name: "Alice" }]);
220
221 Ok(())
222}
223
224#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(scan))]
225pub async fn query_macro_complex_boolean(test: &mut Test) -> Result<()> {
226 let mut db = setup(test).await;
227
228 toasty::create!(User::[
229 { name: "Alice", age: 30 },
230 { name: "Bob", age: 20 },
231 { name: "Carl", age: 40 },
232 { name: "Diana", age: 10 },
233 ])
234 .exec(&mut db)
235 .await?;
236
237 let users =
239 toasty::query!(User filter not (.age < 18) and (.name == "Alice" or .name == "Carl"))
240 .exec(&mut db)
241 .await?;
242
243 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
244
245 Ok(())
246}
247
248#[driver_test(id(ID), scenario(crate::scenarios::widget_mixed_types))]
249pub async fn query_macro_filter_bool_literal(test: &mut Test) -> Result<()> {
250 let mut db = setup(test).await;
251
252 toasty::create!(Widget::[
253 { label: "on", count: 0, active: true, description: "" },
254 { label: "off", count: 0, active: false, description: "" },
255 ])
256 .exec(&mut db)
257 .await?;
258
259 let widgets = toasty::query!(Widget filter .active == true)
260 .exec(&mut db)
261 .await?;
262
263 assert_struct!(widgets, [{ label: "on" }]);
264
265 Ok(())
266}
267
268#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
271pub async fn query_macro_order_by_asc(test: &mut Test) -> Result<()> {
272 let mut db = setup(test).await;
273
274 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
275 .exec(&mut db)
276 .await?;
277
278 let users = toasty::query!(User ORDER BY .name ASC)
279 .exec(&mut db)
280 .await?;
281 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }]);
282
283 Ok(())
284}
285
286#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
287pub async fn query_macro_order_by_desc(test: &mut Test) -> Result<()> {
288 let mut db = setup(test).await;
289
290 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
291 .exec(&mut db)
292 .await?;
293
294 let users = toasty::query!(User ORDER BY .name DESC)
295 .exec(&mut db)
296 .await?;
297 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }, { name: "Alice" }]);
298
299 Ok(())
300}
301
302#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
303pub async fn query_macro_limit(test: &mut Test) -> Result<()> {
304 let mut db = setup(test).await;
305
306 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
307 .exec(&mut db)
308 .await?;
309
310 let users = toasty::query!(User ORDER BY .name ASC LIMIT 2)
311 .exec(&mut db)
312 .await?;
313 assert_eq!(users.len(), 2);
314 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
315
316 Ok(())
317}
318
319#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
320pub async fn query_macro_offset_and_limit(test: &mut Test) -> Result<()> {
321 let mut db = setup(test).await;
322
323 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }, { name: "Diana" }])
324 .exec(&mut db)
325 .await?;
326
327 let users = toasty::query!(User ORDER BY .name ASC OFFSET 1 LIMIT 2)
329 .exec(&mut db)
330 .await?;
331 assert_struct!(users, [{ name: "Bob" }, { name: "Carl" }]);
332
333 Ok(())
334}
335
336#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(sql))]
337pub async fn query_macro_filter_with_order_by_and_limit(test: &mut Test) -> Result<()> {
338 let mut db = setup(test).await;
339
340 toasty::create!(User::[
341 { name: "Alice", age: 30 },
342 { name: "Bob", age: 25 },
343 { name: "Carl", age: 35 },
344 { name: "Diana", age: 20 },
345 ])
346 .exec(&mut db)
347 .await?;
348
349 let users = toasty::query!(User FILTER .age > 20 ORDER BY .name DESC LIMIT 2)
351 .exec(&mut db)
352 .await?;
353 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }]);
354
355 Ok(())
356}
357
358#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
359pub async fn query_macro_limit_external_ref(test: &mut Test) -> Result<()> {
360 let mut db = setup(test).await;
361
362 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
363 .exec(&mut db)
364 .await?;
365
366 let n = 1;
367 let users = toasty::query!(User ORDER BY .name ASC LIMIT #n)
368 .exec(&mut db)
369 .await?;
370 assert_struct!(users, [{ name: "Alice" }]);
371
372 Ok(())
373}
374
375#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
376pub async fn query_macro_case_insensitive_order_limit(test: &mut Test) -> Result<()> {
377 let mut db = setup(test).await;
378
379 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
380 .exec(&mut db)
381 .await?;
382
383 let users = toasty::query!(User order by .name asc limit 2)
385 .exec(&mut db)
386 .await?;
387 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
388
389 Ok(())
390}
391
392#[driver_test(id(ID))]
397pub async fn query_macro_partition_key_eq(test: &mut Test) -> Result<()> {
398 #[derive(Debug, toasty::Model)]
399 #[key(partition = league, local = name)]
400 struct Team {
401 league: String,
402
403 name: String,
404
405 founded: i64,
406 }
407
408 let mut db = test.setup_db(models!(Team)).await;
409
410 for (league, name, founded) in [
411 ("MLS", "Portland Timbers", 2009),
412 ("MLS", "Seattle Sounders FC", 2007),
413 ("EPL", "Arsenal", 1886),
414 ("EPL", "Chelsea", 1905),
415 ] {
416 toasty::create!(Team {
417 league: league,
418 name: name,
419 founded: founded
420 })
421 .exec(&mut db)
422 .await?;
423 }
424
425 let teams = toasty::query!(Team filter .league == "EPL")
427 .exec(&mut db)
428 .await?;
429
430 assert_struct!(teams, #({ name: "Arsenal" }, { name: "Chelsea" }));
431
432 Ok(())
433}
434
435#[driver_test(id(ID))]
436pub async fn query_macro_partition_and_local_key(test: &mut Test) -> Result<()> {
437 #[derive(Debug, toasty::Model)]
438 #[key(partition = league, local = name)]
439 struct Team {
440 league: String,
441
442 name: String,
443
444 founded: i64,
445 }
446
447 let mut db = test.setup_db(models!(Team)).await;
448
449 for (league, name, founded) in [
450 ("MLS", "Portland Timbers", 2009),
451 ("MLS", "Seattle Sounders FC", 2007),
452 ("EPL", "Arsenal", 1886),
453 ("EPL", "Chelsea", 1905),
454 ] {
455 toasty::create!(Team {
456 league: league,
457 name: name,
458 founded: founded
459 })
460 .exec(&mut db)
461 .await?;
462 }
463
464 let teams = toasty::query!(Team filter .league == "MLS" and .name == "Portland Timbers")
466 .exec(&mut db)
467 .await?;
468
469 assert_struct!(teams, [{ name: "Portland Timbers", founded: 2009 }]);
470
471 Ok(())
472}
473
474#[driver_test(id(ID))]
475pub async fn query_macro_local_key_comparison(test: &mut Test) -> Result<()> {
476 #[derive(Debug, toasty::Model)]
477 #[key(partition = kind, local = timestamp)]
478 struct Event {
479 kind: String,
480
481 timestamp: i64,
482 }
483
484 let mut db = test.setup_db(models!(Event)).await;
485
486 for (kind, ts) in [
487 ("info", 0),
488 ("info", 2),
489 ("info", 4),
490 ("info", 6),
491 ("info", 8),
492 ("info", 10),
493 ("warn", 1),
494 ("warn", 3),
495 ("warn", 5),
496 ] {
497 toasty::create!(Event {
498 kind: kind,
499 timestamp: ts
500 })
501 .exec(&mut db)
502 .await?;
503 }
504
505 let events = toasty::query!(Event filter .kind == "info" and .timestamp > 6)
507 .exec(&mut db)
508 .await?;
509
510 assert_struct!(events, #({ timestamp: 8 }, { timestamp: 10 }));
511
512 let events = toasty::query!(Event filter .kind == "info" and .timestamp <= 4)
514 .exec(&mut db)
515 .await?;
516
517 assert_struct!(events, #({ timestamp: 0 }, { timestamp: 2 }, { timestamp: 4 }));
518
519 Ok(())
520}
521
522#[driver_test(id(ID))]
523pub async fn query_macro_partition_key_external_ref(test: &mut Test) -> Result<()> {
524 #[derive(Debug, toasty::Model)]
525 #[key(partition = league, local = name)]
526 struct Team {
527 league: String,
528
529 name: String,
530
531 founded: i64,
532 }
533
534 let mut db = test.setup_db(models!(Team)).await;
535
536 for (league, name, founded) in [
537 ("MLS", "Portland Timbers", 2009),
538 ("MLS", "Seattle Sounders FC", 2007),
539 ("EPL", "Arsenal", 1886),
540 ] {
541 toasty::create!(Team {
542 league: league,
543 name: name,
544 founded: founded
545 })
546 .exec(&mut db)
547 .await?;
548 }
549
550 let target_league = "MLS";
552 let teams = toasty::query!(Team filter .league == #target_league)
553 .exec(&mut db)
554 .await?;
555
556 assert_struct!(teams, #({ name: "Portland Timbers" }, { name: "Seattle Sounders FC" }));
557
558 Ok(())
559}
560
561#[driver_test(id(ID))]
562pub async fn query_macro_partition_key_with_not(test: &mut Test) -> Result<()> {
563 #[derive(Debug, toasty::Model)]
564 #[key(partition = team, local = name)]
565 struct Player {
566 team: String,
567
568 name: String,
569
570 position: String,
571 }
572
573 let mut db = test.setup_db(models!(Player)).await;
574
575 for (team, name, position) in [
576 ("Timbers", "Diego Valeri", "Midfielder"),
577 ("Timbers", "Fanendo Adi", "Forward"),
578 ("Timbers", "Adam Kwarasey", "Goalkeeper"),
579 ("Sounders", "Clint Dempsey", "Forward"),
580 ] {
581 toasty::create!(Player {
582 team: team,
583 name: name,
584 position: position
585 })
586 .exec(&mut db)
587 .await?;
588 }
589
590 let players =
592 toasty::query!(Player filter .team == "Timbers" and not .position == "Midfielder")
593 .exec(&mut db)
594 .await?;
595
596 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
597
598 Ok(())
599}
600
601#[driver_test(id(ID))]
602pub async fn query_macro_partition_key_with_or(test: &mut Test) -> Result<()> {
603 #[derive(Debug, toasty::Model)]
604 #[key(partition = team, local = name)]
605 struct Player {
606 team: String,
607
608 name: String,
609
610 position: String,
611
612 number: i64,
613 }
614
615 let mut db = test.setup_db(models!(Player)).await;
616
617 for (team, name, position, number) in [
618 ("Timbers", "Diego Valeri", "Midfielder", 8),
619 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
620 ("Timbers", "Fanendo Adi", "Forward", 9),
621 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
622 ("Sounders", "Clint Dempsey", "Forward", 2),
623 ] {
624 toasty::create!(Player {
625 team: team,
626 name: name,
627 position: position,
628 number: number
629 })
630 .exec(&mut db)
631 .await?;
632 }
633
634 let players = toasty::query!(Player filter .team == "Timbers" and (.position == "Forward" or .position == "Goalkeeper"))
636 .exec(&mut db)
637 .await?;
638
639 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
640
641 Ok(())
642}
643
644#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
645pub async fn query_macro_filter_in_list(test: &mut Test) -> Result<()> {
646 let mut db = setup(test).await;
647
648 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
649 .exec(&mut db)
650 .await?;
651
652 let users = toasty::query!(User filter .name IN ["Alice", "Carl"])
654 .exec(&mut db)
655 .await?;
656
657 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
658
659 Ok(())
660}
661
662#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
663pub async fn query_macro_filter_in_list_external_ref(test: &mut Test) -> Result<()> {
664 let mut db = setup(test).await;
665
666 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
667 .exec(&mut db)
668 .await?;
669
670 let names = vec!["Alice", "Bob"];
672 let users = toasty::query!(User filter .name IN #names)
673 .exec(&mut db)
674 .await?;
675
676 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
677
678 Ok(())
679}
680
681#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
682pub async fn query_macro_filter_in_list_with_and(test: &mut Test) -> Result<()> {
683 let mut db = setup(test).await;
684
685 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
686 .exec(&mut db)
687 .await?;
688
689 let users = toasty::query!(User filter .name IN ["Alice", "Bob", "Carl"] and .name != "Bob")
691 .exec(&mut db)
692 .await?;
693
694 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
695
696 Ok(())
697}
698
699#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
700pub async fn query_macro_filter_in_list_by_pk(test: &mut Test) -> Result<()> {
701 let mut db = setup(test).await;
702
703 let mut ids = Vec::new();
705 for name in ["Alice", "Bob", "Carl", "Diana"] {
706 let user = User::create().name(name).exec(&mut db).await?;
707 ids.push(user.id);
708 }
709
710 let target_ids = vec![ids[0], ids[2]]; let users = toasty::query!(User filter .id IN #target_ids)
713 .exec(&mut db)
714 .await?;
715
716 assert_eq!(users.len(), 2);
717 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
718
719 Ok(())
720}