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(sql))]
144pub async fn query_macro_filter_parens(test: &mut Test) -> Result<()> {
145 let mut db = setup(test).await;
146
147 toasty::create!(User::[
148 { name: "Alice", age: 30 },
149 { name: "Bob", age: 20 },
150 { name: "Carl", age: 40 },
151 ])
152 .exec(&mut db)
153 .await?;
154
155 let users = toasty::query!(User filter .name == "Alice" and (.age > 25 or .age < 15))
158 .exec(&mut db)
159 .await?;
160
161 assert_struct!(users, [{ name: "Alice" }]);
162
163 Ok(())
164}
165
166#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
167pub async fn query_macro_filter_external_ref(test: &mut Test) -> Result<()> {
168 let mut db = setup(test).await;
169
170 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
171 .exec(&mut db)
172 .await?;
173
174 let target_name = "Alice";
175 let users = toasty::query!(User filter .name == #target_name)
176 .exec(&mut db)
177 .await?;
178
179 assert_struct!(users, [{ name: "Alice" }]);
180
181 Ok(())
182}
183
184#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
185pub async fn query_macro_filter_external_expr(test: &mut Test) -> Result<()> {
186 let mut db = setup(test).await;
187
188 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
189 .exec(&mut db)
190 .await?;
191
192 fn get_name() -> &'static str {
193 "Bob"
194 }
195
196 let users = toasty::query!(User filter .name == #(get_name()))
197 .exec(&mut db)
198 .await?;
199
200 assert_struct!(users, [{ name: "Bob" }]);
201
202 Ok(())
203}
204
205#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
206pub async fn query_macro_case_insensitive_keywords(test: &mut Test) -> Result<()> {
207 let mut db = setup(test).await;
208
209 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }])
210 .exec(&mut db)
211 .await?;
212
213 let users = toasty::query!(User FILTER .name == "Alice")
215 .exec(&mut db)
216 .await?;
217 assert_struct!(users, [{ name: "Alice" }]);
218
219 let users = toasty::query!(User Filter .name == "Alice" AND .name == "Alice")
221 .exec(&mut db)
222 .await?;
223 assert_struct!(users, [{ name: "Alice" }]);
224
225 Ok(())
226}
227
228#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(scan))]
229pub async fn query_macro_complex_boolean(test: &mut Test) -> Result<()> {
230 let mut db = setup(test).await;
231
232 toasty::create!(User::[
233 { name: "Alice", age: 30 },
234 { name: "Bob", age: 20 },
235 { name: "Carl", age: 40 },
236 { name: "Diana", age: 10 },
237 ])
238 .exec(&mut db)
239 .await?;
240
241 let users =
243 toasty::query!(User filter not (.age < 18) and (.name == "Alice" or .name == "Carl"))
244 .exec(&mut db)
245 .await?;
246
247 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
248
249 Ok(())
250}
251
252#[driver_test(id(ID), requires(sql))]
257pub async fn query_macro_filter_bool_literal(test: &mut Test) -> Result<()> {
258 #[derive(Debug, toasty::Model)]
259 struct Item {
260 #[key]
261 #[auto]
262 id: ID,
263
264 name: String,
265
266 #[index]
267 active: bool,
268 }
269
270 let mut db = test.setup_db(models!(Item)).await;
271
272 toasty::create!(Item::[
273 { name: "on", active: true },
274 { name: "off", active: false },
275 ])
276 .exec(&mut db)
277 .await?;
278
279 let items = toasty::query!(Item filter .active == true)
280 .exec(&mut db)
281 .await?;
282
283 assert_struct!(items, [{ name: "on" }]);
284
285 Ok(())
286}
287
288#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
291pub async fn query_macro_order_by_asc(test: &mut Test) -> Result<()> {
292 let mut db = setup(test).await;
293
294 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
295 .exec(&mut db)
296 .await?;
297
298 let users = toasty::query!(User ORDER BY .name ASC)
299 .exec(&mut db)
300 .await?;
301 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }]);
302
303 Ok(())
304}
305
306#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
307pub async fn query_macro_order_by_desc(test: &mut Test) -> Result<()> {
308 let mut db = setup(test).await;
309
310 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
311 .exec(&mut db)
312 .await?;
313
314 let users = toasty::query!(User ORDER BY .name DESC)
315 .exec(&mut db)
316 .await?;
317 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }, { name: "Alice" }]);
318
319 Ok(())
320}
321
322#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
323pub async fn query_macro_limit(test: &mut Test) -> Result<()> {
324 let mut db = setup(test).await;
325
326 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
327 .exec(&mut db)
328 .await?;
329
330 let users = toasty::query!(User ORDER BY .name ASC LIMIT 2)
331 .exec(&mut db)
332 .await?;
333 assert_eq!(users.len(), 2);
334 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
335
336 Ok(())
337}
338
339#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
340pub async fn query_macro_offset_and_limit(test: &mut Test) -> Result<()> {
341 let mut db = setup(test).await;
342
343 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }, { name: "Diana" }])
344 .exec(&mut db)
345 .await?;
346
347 let users = toasty::query!(User ORDER BY .name ASC OFFSET 1 LIMIT 2)
349 .exec(&mut db)
350 .await?;
351 assert_struct!(users, [{ name: "Bob" }, { name: "Carl" }]);
352
353 Ok(())
354}
355
356#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(sql))]
357pub async fn query_macro_filter_with_order_by_and_limit(test: &mut Test) -> Result<()> {
358 let mut db = setup(test).await;
359
360 toasty::create!(User::[
361 { name: "Alice", age: 30 },
362 { name: "Bob", age: 25 },
363 { name: "Carl", age: 35 },
364 { name: "Diana", age: 20 },
365 ])
366 .exec(&mut db)
367 .await?;
368
369 let users = toasty::query!(User FILTER .age > 20 ORDER BY .name DESC LIMIT 2)
371 .exec(&mut db)
372 .await?;
373 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }]);
374
375 Ok(())
376}
377
378#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
379pub async fn query_macro_limit_external_ref(test: &mut Test) -> Result<()> {
380 let mut db = setup(test).await;
381
382 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
383 .exec(&mut db)
384 .await?;
385
386 let n = 1;
387 let users = toasty::query!(User ORDER BY .name ASC LIMIT #n)
388 .exec(&mut db)
389 .await?;
390 assert_struct!(users, [{ name: "Alice" }]);
391
392 Ok(())
393}
394
395#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
396pub async fn query_macro_case_insensitive_order_limit(test: &mut Test) -> Result<()> {
397 let mut db = setup(test).await;
398
399 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
400 .exec(&mut db)
401 .await?;
402
403 let users = toasty::query!(User order by .name asc limit 2)
405 .exec(&mut db)
406 .await?;
407 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
408
409 Ok(())
410}
411
412#[driver_test(id(ID))]
417pub async fn query_macro_partition_key_eq(test: &mut Test) -> Result<()> {
418 #[derive(Debug, toasty::Model)]
419 #[key(partition = league, local = name)]
420 struct Team {
421 league: String,
422
423 name: String,
424
425 founded: i64,
426 }
427
428 let mut db = test.setup_db(models!(Team)).await;
429
430 for (league, name, founded) in [
431 ("MLS", "Portland Timbers", 2009),
432 ("MLS", "Seattle Sounders FC", 2007),
433 ("EPL", "Arsenal", 1886),
434 ("EPL", "Chelsea", 1905),
435 ] {
436 toasty::create!(Team {
437 league: league,
438 name: name,
439 founded: founded
440 })
441 .exec(&mut db)
442 .await?;
443 }
444
445 let teams = toasty::query!(Team filter .league == "EPL")
447 .exec(&mut db)
448 .await?;
449
450 assert_struct!(teams, #({ name: "Arsenal" }, { name: "Chelsea" }));
451
452 Ok(())
453}
454
455#[driver_test(id(ID))]
456pub async fn query_macro_partition_and_local_key(test: &mut Test) -> Result<()> {
457 #[derive(Debug, toasty::Model)]
458 #[key(partition = league, local = name)]
459 struct Team {
460 league: String,
461
462 name: String,
463
464 founded: i64,
465 }
466
467 let mut db = test.setup_db(models!(Team)).await;
468
469 for (league, name, founded) in [
470 ("MLS", "Portland Timbers", 2009),
471 ("MLS", "Seattle Sounders FC", 2007),
472 ("EPL", "Arsenal", 1886),
473 ("EPL", "Chelsea", 1905),
474 ] {
475 toasty::create!(Team {
476 league: league,
477 name: name,
478 founded: founded
479 })
480 .exec(&mut db)
481 .await?;
482 }
483
484 let teams = toasty::query!(Team filter .league == "MLS" and .name == "Portland Timbers")
486 .exec(&mut db)
487 .await?;
488
489 assert_struct!(teams, [{ name: "Portland Timbers", founded: 2009 }]);
490
491 Ok(())
492}
493
494#[driver_test(id(ID))]
495pub async fn query_macro_local_key_comparison(test: &mut Test) -> Result<()> {
496 #[derive(Debug, toasty::Model)]
497 #[key(partition = kind, local = timestamp)]
498 struct Event {
499 kind: String,
500
501 timestamp: i64,
502 }
503
504 let mut db = test.setup_db(models!(Event)).await;
505
506 for (kind, ts) in [
507 ("info", 0),
508 ("info", 2),
509 ("info", 4),
510 ("info", 6),
511 ("info", 8),
512 ("info", 10),
513 ("warn", 1),
514 ("warn", 3),
515 ("warn", 5),
516 ] {
517 toasty::create!(Event {
518 kind: kind,
519 timestamp: ts
520 })
521 .exec(&mut db)
522 .await?;
523 }
524
525 let events = toasty::query!(Event filter .kind == "info" and .timestamp > 6)
527 .exec(&mut db)
528 .await?;
529
530 assert_struct!(events, #({ timestamp: 8 }, { timestamp: 10 }));
531
532 let events = toasty::query!(Event filter .kind == "info" and .timestamp <= 4)
534 .exec(&mut db)
535 .await?;
536
537 assert_struct!(events, #({ timestamp: 0 }, { timestamp: 2 }, { timestamp: 4 }));
538
539 Ok(())
540}
541
542#[driver_test(id(ID))]
543pub async fn query_macro_partition_key_external_ref(test: &mut Test) -> Result<()> {
544 #[derive(Debug, toasty::Model)]
545 #[key(partition = league, local = name)]
546 struct Team {
547 league: String,
548
549 name: String,
550
551 founded: i64,
552 }
553
554 let mut db = test.setup_db(models!(Team)).await;
555
556 for (league, name, founded) in [
557 ("MLS", "Portland Timbers", 2009),
558 ("MLS", "Seattle Sounders FC", 2007),
559 ("EPL", "Arsenal", 1886),
560 ] {
561 toasty::create!(Team {
562 league: league,
563 name: name,
564 founded: founded
565 })
566 .exec(&mut db)
567 .await?;
568 }
569
570 let target_league = "MLS";
572 let teams = toasty::query!(Team filter .league == #target_league)
573 .exec(&mut db)
574 .await?;
575
576 assert_struct!(teams, #({ name: "Portland Timbers" }, { name: "Seattle Sounders FC" }));
577
578 Ok(())
579}
580
581#[driver_test(id(ID))]
582pub async fn query_macro_partition_key_with_not(test: &mut Test) -> Result<()> {
583 #[derive(Debug, toasty::Model)]
584 #[key(partition = team, local = name)]
585 struct Player {
586 team: String,
587
588 name: String,
589
590 position: String,
591 }
592
593 let mut db = test.setup_db(models!(Player)).await;
594
595 for (team, name, position) in [
596 ("Timbers", "Diego Valeri", "Midfielder"),
597 ("Timbers", "Fanendo Adi", "Forward"),
598 ("Timbers", "Adam Kwarasey", "Goalkeeper"),
599 ("Sounders", "Clint Dempsey", "Forward"),
600 ] {
601 toasty::create!(Player {
602 team: team,
603 name: name,
604 position: position
605 })
606 .exec(&mut db)
607 .await?;
608 }
609
610 let players =
612 toasty::query!(Player filter .team == "Timbers" and not .position == "Midfielder")
613 .exec(&mut db)
614 .await?;
615
616 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
617
618 Ok(())
619}
620
621#[driver_test(id(ID))]
622pub async fn query_macro_partition_key_with_or(test: &mut Test) -> Result<()> {
623 #[derive(Debug, toasty::Model)]
624 #[key(partition = team, local = name)]
625 struct Player {
626 team: String,
627
628 name: String,
629
630 position: String,
631
632 number: i64,
633 }
634
635 let mut db = test.setup_db(models!(Player)).await;
636
637 for (team, name, position, number) in [
638 ("Timbers", "Diego Valeri", "Midfielder", 8),
639 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
640 ("Timbers", "Fanendo Adi", "Forward", 9),
641 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
642 ("Sounders", "Clint Dempsey", "Forward", 2),
643 ] {
644 toasty::create!(Player {
645 team: team,
646 name: name,
647 position: position,
648 number: number
649 })
650 .exec(&mut db)
651 .await?;
652 }
653
654 let players = toasty::query!(Player filter .team == "Timbers" and (.position == "Forward" or .position == "Goalkeeper"))
656 .exec(&mut db)
657 .await?;
658
659 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
660
661 Ok(())
662}
663
664#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
665pub async fn query_macro_filter_in_list(test: &mut Test) -> Result<()> {
666 let mut db = setup(test).await;
667
668 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
669 .exec(&mut db)
670 .await?;
671
672 let users = toasty::query!(User filter .name IN ["Alice", "Carl"])
674 .exec(&mut db)
675 .await?;
676
677 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
678
679 Ok(())
680}
681
682#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
683pub async fn query_macro_filter_in_list_external_ref(test: &mut Test) -> Result<()> {
684 let mut db = setup(test).await;
685
686 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
687 .exec(&mut db)
688 .await?;
689
690 let names = vec!["Alice", "Bob"];
692 let users = toasty::query!(User filter .name IN #names)
693 .exec(&mut db)
694 .await?;
695
696 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
697
698 Ok(())
699}
700
701#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(scan))]
702pub async fn query_macro_filter_in_list_with_and(test: &mut Test) -> Result<()> {
703 let mut db = setup(test).await;
704
705 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
706 .exec(&mut db)
707 .await?;
708
709 let users = toasty::query!(User filter .name IN ["Alice", "Bob", "Carl"] and .name != "Bob")
711 .exec(&mut db)
712 .await?;
713
714 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
715
716 Ok(())
717}
718
719#[driver_test(id(ID))]
720pub async fn query_macro_filter_in_list_by_pk(test: &mut Test) -> Result<()> {
721 #[derive(Debug, toasty::Model)]
722 struct Item {
723 #[key]
724 #[auto]
725 id: ID,
726
727 name: String,
728 }
729
730 let mut db = test.setup_db(models!(Item)).await;
731
732 let mut ids = Vec::new();
734 for name in ["Alice", "Bob", "Carl", "Diana"] {
735 let item = Item::create().name(name).exec(&mut db).await?;
736 ids.push(item.id);
737 }
738
739 let target_ids = vec![ids[0], ids[2]]; let items = toasty::query!(Item filter .id IN #target_ids)
742 .exec(&mut db)
743 .await?;
744
745 assert_eq!(items.len(), 2);
746 assert_struct!(items, #({ name: "Alice" }, { name: "Carl" }));
747
748 Ok(())
749}