1use crate::prelude::*;
2
3#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
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(sql))]
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(sql))]
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(sql))]
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(sql))]
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(sql))]
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(sql))]
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))]
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(sql))]
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(sql))]
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(sql))]
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(sql))]
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), requires(sql))]
249pub async fn query_macro_filter_bool_literal(test: &mut Test) -> Result<()> {
250 #[derive(Debug, toasty::Model)]
251 struct Item {
252 #[key]
253 #[auto]
254 id: ID,
255
256 name: String,
257
258 #[index]
259 active: bool,
260 }
261
262 let mut db = test.setup_db(models!(Item)).await;
263
264 toasty::create!(Item::[
265 { name: "on", active: true },
266 { name: "off", active: false },
267 ])
268 .exec(&mut db)
269 .await?;
270
271 let items = toasty::query!(Item filter .active == true)
272 .exec(&mut db)
273 .await?;
274
275 assert_struct!(items, [{ name: "on" }]);
276
277 Ok(())
278}
279
280#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
283pub async fn query_macro_order_by_asc(test: &mut Test) -> Result<()> {
284 let mut db = setup(test).await;
285
286 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
287 .exec(&mut db)
288 .await?;
289
290 let users = toasty::query!(User ORDER BY .name ASC)
291 .exec(&mut db)
292 .await?;
293 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }]);
294
295 Ok(())
296}
297
298#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
299pub async fn query_macro_order_by_desc(test: &mut Test) -> Result<()> {
300 let mut db = setup(test).await;
301
302 toasty::create!(User::[{ name: "Carl" }, { name: "Alice" }, { name: "Bob" }])
303 .exec(&mut db)
304 .await?;
305
306 let users = toasty::query!(User ORDER BY .name DESC)
307 .exec(&mut db)
308 .await?;
309 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }, { name: "Alice" }]);
310
311 Ok(())
312}
313
314#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
315pub async fn query_macro_limit(test: &mut Test) -> Result<()> {
316 let mut db = setup(test).await;
317
318 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
319 .exec(&mut db)
320 .await?;
321
322 let users = toasty::query!(User ORDER BY .name ASC LIMIT 2)
323 .exec(&mut db)
324 .await?;
325 assert_eq!(users.len(), 2);
326 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
327
328 Ok(())
329}
330
331#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
332pub async fn query_macro_offset_and_limit(test: &mut Test) -> Result<()> {
333 let mut db = setup(test).await;
334
335 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }, { name: "Diana" }])
336 .exec(&mut db)
337 .await?;
338
339 let users = toasty::query!(User ORDER BY .name ASC OFFSET 1 LIMIT 2)
341 .exec(&mut db)
342 .await?;
343 assert_struct!(users, [{ name: "Bob" }, { name: "Carl" }]);
344
345 Ok(())
346}
347
348#[driver_test(id(ID), scenario(crate::scenarios::user_with_age), requires(sql))]
349pub async fn query_macro_filter_with_order_by_and_limit(test: &mut Test) -> Result<()> {
350 let mut db = setup(test).await;
351
352 toasty::create!(User::[
353 { name: "Alice", age: 30 },
354 { name: "Bob", age: 25 },
355 { name: "Carl", age: 35 },
356 { name: "Diana", age: 20 },
357 ])
358 .exec(&mut db)
359 .await?;
360
361 let users = toasty::query!(User FILTER .age > 20 ORDER BY .name DESC LIMIT 2)
363 .exec(&mut db)
364 .await?;
365 assert_struct!(users, [{ name: "Carl" }, { name: "Bob" }]);
366
367 Ok(())
368}
369
370#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
371pub async fn query_macro_limit_external_ref(test: &mut Test) -> Result<()> {
372 let mut db = setup(test).await;
373
374 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
375 .exec(&mut db)
376 .await?;
377
378 let n = 1;
379 let users = toasty::query!(User ORDER BY .name ASC LIMIT #n)
380 .exec(&mut db)
381 .await?;
382 assert_struct!(users, [{ name: "Alice" }]);
383
384 Ok(())
385}
386
387#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
388pub async fn query_macro_case_insensitive_order_limit(test: &mut Test) -> Result<()> {
389 let mut db = setup(test).await;
390
391 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
392 .exec(&mut db)
393 .await?;
394
395 let users = toasty::query!(User order by .name asc limit 2)
397 .exec(&mut db)
398 .await?;
399 assert_struct!(users, [{ name: "Alice" }, { name: "Bob" }]);
400
401 Ok(())
402}
403
404#[driver_test(id(ID))]
409pub async fn query_macro_partition_key_eq(test: &mut Test) -> Result<()> {
410 #[derive(Debug, toasty::Model)]
411 #[key(partition = league, local = name)]
412 struct Team {
413 league: String,
414
415 name: String,
416
417 founded: i64,
418 }
419
420 let mut db = test.setup_db(models!(Team)).await;
421
422 for (league, name, founded) in [
423 ("MLS", "Portland Timbers", 2009),
424 ("MLS", "Seattle Sounders FC", 2007),
425 ("EPL", "Arsenal", 1886),
426 ("EPL", "Chelsea", 1905),
427 ] {
428 toasty::create!(Team {
429 league: league,
430 name: name,
431 founded: founded
432 })
433 .exec(&mut db)
434 .await?;
435 }
436
437 let teams = toasty::query!(Team filter .league == "EPL")
439 .exec(&mut db)
440 .await?;
441
442 assert_struct!(teams, #({ name: "Arsenal" }, { name: "Chelsea" }));
443
444 Ok(())
445}
446
447#[driver_test(id(ID))]
448pub async fn query_macro_partition_and_local_key(test: &mut Test) -> Result<()> {
449 #[derive(Debug, toasty::Model)]
450 #[key(partition = league, local = name)]
451 struct Team {
452 league: String,
453
454 name: String,
455
456 founded: i64,
457 }
458
459 let mut db = test.setup_db(models!(Team)).await;
460
461 for (league, name, founded) in [
462 ("MLS", "Portland Timbers", 2009),
463 ("MLS", "Seattle Sounders FC", 2007),
464 ("EPL", "Arsenal", 1886),
465 ("EPL", "Chelsea", 1905),
466 ] {
467 toasty::create!(Team {
468 league: league,
469 name: name,
470 founded: founded
471 })
472 .exec(&mut db)
473 .await?;
474 }
475
476 let teams = toasty::query!(Team filter .league == "MLS" and .name == "Portland Timbers")
478 .exec(&mut db)
479 .await?;
480
481 assert_struct!(teams, [{ name: "Portland Timbers", founded: 2009 }]);
482
483 Ok(())
484}
485
486#[driver_test(id(ID))]
487pub async fn query_macro_local_key_comparison(test: &mut Test) -> Result<()> {
488 #[derive(Debug, toasty::Model)]
489 #[key(partition = kind, local = timestamp)]
490 struct Event {
491 kind: String,
492
493 timestamp: i64,
494 }
495
496 let mut db = test.setup_db(models!(Event)).await;
497
498 for (kind, ts) in [
499 ("info", 0),
500 ("info", 2),
501 ("info", 4),
502 ("info", 6),
503 ("info", 8),
504 ("info", 10),
505 ("warn", 1),
506 ("warn", 3),
507 ("warn", 5),
508 ] {
509 toasty::create!(Event {
510 kind: kind,
511 timestamp: ts
512 })
513 .exec(&mut db)
514 .await?;
515 }
516
517 let events = toasty::query!(Event filter .kind == "info" and .timestamp > 6)
519 .exec(&mut db)
520 .await?;
521
522 assert_struct!(events, #({ timestamp: 8 }, { timestamp: 10 }));
523
524 let events = toasty::query!(Event filter .kind == "info" and .timestamp <= 4)
526 .exec(&mut db)
527 .await?;
528
529 assert_struct!(events, #({ timestamp: 0 }, { timestamp: 2 }, { timestamp: 4 }));
530
531 Ok(())
532}
533
534#[driver_test(id(ID))]
535pub async fn query_macro_partition_key_external_ref(test: &mut Test) -> Result<()> {
536 #[derive(Debug, toasty::Model)]
537 #[key(partition = league, local = name)]
538 struct Team {
539 league: String,
540
541 name: String,
542
543 founded: i64,
544 }
545
546 let mut db = test.setup_db(models!(Team)).await;
547
548 for (league, name, founded) in [
549 ("MLS", "Portland Timbers", 2009),
550 ("MLS", "Seattle Sounders FC", 2007),
551 ("EPL", "Arsenal", 1886),
552 ] {
553 toasty::create!(Team {
554 league: league,
555 name: name,
556 founded: founded
557 })
558 .exec(&mut db)
559 .await?;
560 }
561
562 let target_league = "MLS";
564 let teams = toasty::query!(Team filter .league == #target_league)
565 .exec(&mut db)
566 .await?;
567
568 assert_struct!(teams, #({ name: "Portland Timbers" }, { name: "Seattle Sounders FC" }));
569
570 Ok(())
571}
572
573#[driver_test(id(ID))]
574pub async fn query_macro_partition_key_with_not(test: &mut Test) -> Result<()> {
575 #[derive(Debug, toasty::Model)]
576 #[key(partition = team, local = name)]
577 struct Player {
578 team: String,
579
580 name: String,
581
582 position: String,
583 }
584
585 let mut db = test.setup_db(models!(Player)).await;
586
587 for (team, name, position) in [
588 ("Timbers", "Diego Valeri", "Midfielder"),
589 ("Timbers", "Fanendo Adi", "Forward"),
590 ("Timbers", "Adam Kwarasey", "Goalkeeper"),
591 ("Sounders", "Clint Dempsey", "Forward"),
592 ] {
593 toasty::create!(Player {
594 team: team,
595 name: name,
596 position: position
597 })
598 .exec(&mut db)
599 .await?;
600 }
601
602 let players =
604 toasty::query!(Player filter .team == "Timbers" and not .position == "Midfielder")
605 .exec(&mut db)
606 .await?;
607
608 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
609
610 Ok(())
611}
612
613#[driver_test(id(ID))]
614pub async fn query_macro_partition_key_with_or(test: &mut Test) -> Result<()> {
615 #[derive(Debug, toasty::Model)]
616 #[key(partition = team, local = name)]
617 struct Player {
618 team: String,
619
620 name: String,
621
622 position: String,
623
624 number: i64,
625 }
626
627 let mut db = test.setup_db(models!(Player)).await;
628
629 for (team, name, position, number) in [
630 ("Timbers", "Diego Valeri", "Midfielder", 8),
631 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
632 ("Timbers", "Fanendo Adi", "Forward", 9),
633 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
634 ("Sounders", "Clint Dempsey", "Forward", 2),
635 ] {
636 toasty::create!(Player {
637 team: team,
638 name: name,
639 position: position,
640 number: number
641 })
642 .exec(&mut db)
643 .await?;
644 }
645
646 let players = toasty::query!(Player filter .team == "Timbers" and (.position == "Forward" or .position == "Goalkeeper"))
648 .exec(&mut db)
649 .await?;
650
651 assert_struct!(players, #({ name: "Adam Kwarasey" }, { name: "Fanendo Adi" }));
652
653 Ok(())
654}
655
656#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
657pub async fn query_macro_filter_in_list(test: &mut Test) -> Result<()> {
658 let mut db = setup(test).await;
659
660 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
661 .exec(&mut db)
662 .await?;
663
664 let users = toasty::query!(User filter .name IN ["Alice", "Carl"])
666 .exec(&mut db)
667 .await?;
668
669 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
670
671 Ok(())
672}
673
674#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
675pub async fn query_macro_filter_in_list_external_ref(test: &mut Test) -> Result<()> {
676 let mut db = setup(test).await;
677
678 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
679 .exec(&mut db)
680 .await?;
681
682 let names = vec!["Alice", "Bob"];
684 let users = toasty::query!(User filter .name IN #names)
685 .exec(&mut db)
686 .await?;
687
688 assert_struct!(users, #({ name: "Alice" }, { name: "Bob" }));
689
690 Ok(())
691}
692
693#[driver_test(id(ID), scenario(crate::scenarios::two_models), requires(sql))]
694pub async fn query_macro_filter_in_list_with_and(test: &mut Test) -> Result<()> {
695 let mut db = setup(test).await;
696
697 toasty::create!(User::[{ name: "Alice" }, { name: "Bob" }, { name: "Carl" }])
698 .exec(&mut db)
699 .await?;
700
701 let users = toasty::query!(User filter .name IN ["Alice", "Bob", "Carl"] and .name != "Bob")
703 .exec(&mut db)
704 .await?;
705
706 assert_struct!(users, #({ name: "Alice" }, { name: "Carl" }));
707
708 Ok(())
709}
710
711#[driver_test(id(ID))]
712pub async fn query_macro_filter_in_list_by_pk(test: &mut Test) -> Result<()> {
713 #[derive(Debug, toasty::Model)]
714 struct Item {
715 #[key]
716 #[auto]
717 id: ID,
718
719 name: String,
720 }
721
722 let mut db = test.setup_db(models!(Item)).await;
723
724 let mut ids = Vec::new();
726 for name in ["Alice", "Bob", "Carl", "Diana"] {
727 let item = Item::create().name(name).exec(&mut db).await?;
728 ids.push(item.id);
729 }
730
731 let target_ids = vec![ids[0], ids[2]]; let items = toasty::query!(Item filter .id IN #target_ids)
734 .exec(&mut db)
735 .await?;
736
737 assert_eq!(items.len(), 2);
738 assert_struct!(items, #({ name: "Alice" }, { name: "Carl" }));
739
740 Ok(())
741}