1use crate::prelude::*;
4use toasty_core::{
5 driver::Operation,
6 stmt::{Expr, ExprSet, Statement},
7};
8
9#[driver_test(id(ID))]
10pub async fn query_index_eq(test: &mut Test) -> Result<()> {
11 #[derive(Debug, toasty::Model)]
12 struct User {
13 #[key]
14 #[auto]
15 id: ID,
16
17 #[index]
18 name: String,
19
20 email: String,
21 }
22
23 let mut db = test.setup_db(models!(User)).await;
24
25 for &(name, email) in &[
27 ("one", "one@example.com"),
28 ("two", "two@example.com"),
29 ("three", "three@example.com"),
30 ] {
31 User::create().name(name).email(email).exec(&mut db).await?;
32 }
33
34 let users = User::filter_by_name("one").exec(&mut db).await?;
35
36 assert_eq!(1, users.len());
37 assert_eq!("one", users[0].name);
38
39 User::create()
42 .name("one")
43 .email("one-two@example.com")
44 .exec(&mut db)
45 .await?;
46
47 let mut users = User::filter_by_name("one").exec(&mut db).await?;
48
49 users.sort_by_key(|u| u.email.clone());
50
51 assert_eq!(2, users.len());
52 assert_eq!("one", users[0].name);
53 assert_eq!("one-two@example.com", users[0].email);
54
55 assert_eq!("one", users[1].name);
56 assert_eq!("one@example.com", users[1].email);
57 Ok(())
58}
59
60#[driver_test(id(ID))]
61pub async fn query_partition_key_string_eq(test: &mut Test) -> Result<()> {
62 #[derive(Debug, toasty::Model)]
63 #[key(partition = league, local = name)]
64 struct Team {
65 league: String,
66
67 name: String,
68
69 founded: i64,
70 }
71
72 let mut db = test.setup_db(models!(Team)).await;
73
74 for (league, name, founded) in [
76 ("MLS", "Portland Timbers", 2009),
77 ("MLS", "Seattle Sounders FC", 2007),
78 ("MLS", "Vancouver Whitecaps FC", 2009),
79 ("MLS", "Los Angeles Football Club", 2014),
80 ("MLS", "San Jose Earthquakes", 1994),
81 ("MLS", "LA Galaxy", 1994),
82 ("EPL", "Arsenal", 1886),
83 ("EPL", "Chelsea", 1905),
84 ("EPL", "Manchester United", 1878),
85 ("EPL", "Tottenham", 1882),
86 ("La Liga", "FC Barcelona", 1899),
87 ("La Liga", "Girona FC", 1930),
88 ("La Liga", "Real Madrid", 1902),
89 ("La Liga", "Atlético Madrid", 1903),
90 ]
91 .into_iter()
92 {
93 Team::create()
94 .league(league)
95 .name(name)
96 .founded(founded)
97 .exec(&mut db)
98 .await?;
99 }
100
101 let teams = Team::filter(Team::fields().league().eq("EPL"))
103 .exec(&mut db)
104 .await?;
105
106 let mut names = teams.iter().map(|team| &team.name).collect::<Vec<_>>();
107 names.sort();
108
109 assert_eq!(
110 names,
111 ["Arsenal", "Chelsea", "Manchester United", "Tottenham"]
112 );
113
114 let teams = Team::filter(
116 Team::fields()
117 .league()
118 .eq("MLS")
119 .and(Team::fields().name().eq("Portland Timbers")),
120 )
121 .exec(&mut db)
122 .await?;
123
124 let mut names = teams.iter().map(|team| &team.name).collect::<Vec<_>>();
125 names.sort();
126
127 assert_eq!(names, ["Portland Timbers"]);
128
129 let teams = Team::filter(
131 Team::fields()
132 .league()
133 .eq("MLS")
134 .and(Team::fields().founded().eq(2009)),
135 )
136 .exec(&mut db)
137 .await?;
138
139 let mut names = teams.iter().map(|team| &team.name).collect::<Vec<_>>();
140 names.sort();
141
142 assert_eq!(names, ["Portland Timbers", "Vancouver Whitecaps FC"]);
143
144 let teams = Team::filter(
146 Team::fields()
147 .league()
148 .eq("MLS")
149 .and(Team::fields().founded().eq(2009))
150 .and(Team::fields().name().eq("Portland Timbers")),
151 )
152 .exec(&mut db)
153 .await?;
154
155 assert_eq!(1, teams.len());
156 assert!(teams.iter().all(|team| team.founded == 2009));
157
158 let mut names = teams.iter().map(|team| &team.name).collect::<Vec<_>>();
159 names.sort();
160
161 assert_eq!(names, ["Portland Timbers"]);
162
163 let teams = Team::filter(
165 Team::fields()
166 .league()
167 .eq("MLS")
168 .and(Team::fields().founded().eq(2009))
169 .and(Team::fields().name().eq("LA Galaxy")),
170 )
171 .exec(&mut db)
172 .await?;
173
174 assert!(teams.is_empty());
175 Ok(())
176}
177
178#[driver_test(id(ID))]
179pub async fn query_local_key_cmp(test: &mut Test) -> Result<()> {
180 #[derive(Debug, toasty::Model)]
181 #[key(partition = kind, local = timestamp)]
182 struct Event {
183 kind: String,
184
185 timestamp: i64,
186 }
187
188 let mut db = test.setup_db(models!(Event)).await;
189
190 for (kind, ts) in [
192 ("info", 0),
193 ("warn", 1),
194 ("info", 2),
195 ("warn", 3),
196 ("info", 4),
197 ("warn", 5),
198 ("info", 6),
199 ("warn", 7),
200 ("info", 8),
201 ("warn", 9),
202 ("info", 10),
203 ("warn", 11),
204 ("info", 12),
205 ("warn", 13),
206 ("info", 14),
207 ("warn", 15),
208 ("info", 16),
209 ("warn", 17),
210 ("info", 18),
211 ("warn", 19),
212 ] {
213 Event::create()
214 .kind(kind)
215 .timestamp(ts)
216 .exec(&mut db)
217 .await?;
218 }
219
220 let events: Vec<_> = Event::filter_by_kind("info")
221 .filter(Event::fields().timestamp().ne(10))
222 .exec(&mut db)
223 .await?;
224
225 assert_eq_unordered!(
226 events.iter().map(|event| event.timestamp),
227 [&0, &2, &4, &6, &8, &12, &14, &16, &18,]
228 );
229
230 let events: Vec<_> = Event::filter_by_kind("info")
231 .filter(Event::fields().timestamp().gt(10))
232 .exec(&mut db)
233 .await?;
234
235 assert_eq_unordered!(
236 events.iter().map(|event| event.timestamp),
237 [&12, &14, &16, &18,]
238 );
239
240 let events: Vec<_> = Event::filter_by_kind("info")
241 .filter(Event::fields().timestamp().ge(10))
242 .exec(&mut db)
243 .await?;
244
245 assert_eq_unordered!(
246 events.iter().map(|event| event.timestamp),
247 [&10, &12, &14, &16, &18,]
248 );
249
250 let events: Vec<_> = Event::filter_by_kind("info")
251 .filter(Event::fields().timestamp().lt(10))
252 .exec(&mut db)
253 .await?;
254
255 assert_eq_unordered!(
256 events.iter().map(|event| event.timestamp),
257 [&0, &2, &4, &6, &8]
258 );
259
260 let events: Vec<_> = Event::filter_by_kind("info")
261 .filter(Event::fields().timestamp().le(10))
262 .exec(&mut db)
263 .await?;
264
265 assert_eq_unordered!(
266 events.iter().map(|event| event.timestamp),
267 [&0, &2, &4, &6, &8, &10]
268 );
269 Ok(())
270}
271
272#[driver_test(id(ID))]
273pub async fn query_or_basic(test: &mut Test) -> Result<()> {
274 #[derive(Debug, toasty::Model)]
275 struct User {
276 #[key]
277 #[auto]
278 id: ID,
279
280 name: String,
281
282 #[allow(dead_code)]
283 age: i64,
284 }
285
286 let mut db = test.setup_db(models!(User)).await;
287 let _name_column = db.schema().table_for(User::id()).columns[1].id;
288 let _age_column = db.schema().table_for(User::id()).columns[2].id;
289
290 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
292 User::create().name(name).age(age).exec(&mut db).await?;
293 }
294
295 test.log().clear();
297
298 let result = User::filter(
300 User::fields()
301 .name()
302 .eq("Alice")
303 .or(User::fields().age().eq(35)),
304 )
305 .exec(&mut db)
306 .await;
307
308 if test.capability().sql {
309 let users = result?;
310 assert_eq!(2, users.len());
311 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
312 names.sort();
313 assert_eq!(names, ["Alice", "Charlie"]);
314
315 let (op, _) = test.log().pop();
317
318 assert_struct!(&op, Operation::QuerySql(_ {
319 stmt: Statement::Query(_ {
320 body: ExprSet::Select(_ {
321 filter.expr: Some(Expr::Or(_ {
322 ..
340 })),
341 ..
342 }),
343 ..
344 }),
345 ..
346 }));
347 } else {
348 assert!(
351 result.is_err(),
352 "Expected error for OR query without key condition on non-SQL database"
353 );
354 }
355 Ok(())
356}
357
358#[driver_test(id(ID))]
359pub async fn query_or_multiple(test: &mut Test) -> Result<()> {
360 #[derive(Debug, toasty::Model)]
361 struct User {
362 #[key]
363 #[auto]
364 id: ID,
365
366 name: String,
367
368 #[allow(dead_code)]
369 age: i64,
370 }
371
372 let mut db = test.setup_db(models!(User)).await;
373
374 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
376 User::create().name(name).age(age).exec(&mut db).await?;
377 }
378
379 let result = User::filter(
381 User::fields()
382 .name()
383 .eq("Alice")
384 .or(User::fields().age().eq(35))
385 .or(User::fields().age().eq(40)),
386 )
387 .exec(&mut db)
388 .await;
389
390 if test.capability().sql {
391 let users = result?;
392 assert_eq!(3, users.len());
393 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
394 names.sort();
395 assert_eq!(names, ["Alice", "Charlie", "Diana"]);
396 } else {
397 assert!(
400 result.is_err(),
401 "Expected error for OR query without key condition on non-SQL database"
402 );
403 }
404 Ok(())
405}
406
407#[driver_test(id(ID))]
408pub async fn query_or_and_combined(test: &mut Test) -> Result<()> {
409 #[derive(Debug, toasty::Model)]
410 struct User {
411 #[key]
412 #[auto]
413 id: ID,
414
415 name: String,
416
417 #[allow(dead_code)]
418 age: i64,
419
420 #[allow(dead_code)]
421 active: bool,
422 }
423
424 let mut db = test.setup_db(models!(User)).await;
425
426 for (name, age, active) in [
428 ("Alice", 25, true),
429 ("Bob", 30, false),
430 ("Charlie", 35, true),
431 ("Diana", 40, false),
432 ("Eve", 25, false),
433 ] {
434 User::create()
435 .name(name)
436 .age(age)
437 .active(active)
438 .exec(&mut db)
439 .await?;
440 }
441
442 let result = User::filter(
444 User::fields()
445 .name()
446 .eq("Alice")
447 .or(User::fields().age().eq(35))
448 .and(User::fields().active().eq(true)),
449 )
450 .exec(&mut db)
451 .await;
452
453 if test.capability().sql {
454 let users = result?;
455 assert_eq!(2, users.len());
456 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
457 names.sort();
458 assert_eq!(names, ["Alice", "Charlie"]);
459 } else {
460 assert!(
463 result.is_err(),
464 "Expected error for OR query without key condition on non-SQL database"
465 );
466 }
467 Ok(())
468}
469
470#[driver_test(id(ID))]
471pub async fn query_or_with_index(test: &mut Test) -> Result<()> {
472 #[derive(Debug, toasty::Model)]
473 #[key(partition = team, local = name)]
474 struct Player {
475 team: String,
476
477 name: String,
478
479 #[allow(dead_code)]
480 position: String,
481
482 #[allow(dead_code)]
483 number: i64,
484 }
485
486 let mut db = test.setup_db(models!(Player)).await;
487
488 for (team, name, position, number) in [
490 ("Timbers", "Diego Valeri", "Midfielder", 8),
491 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
492 ("Timbers", "Diego Chara", "Midfielder", 21),
493 ("Timbers", "Fanendo Adi", "Forward", 9),
494 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
495 ("Sounders", "Clint Dempsey", "Forward", 2),
496 ("Sounders", "Obafemi Martins", "Forward", 9),
497 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
498 ] {
499 Player::create()
500 .team(team)
501 .name(name)
502 .position(position)
503 .number(number)
504 .exec(&mut db)
505 .await?;
506 }
507
508 let players = Player::filter(
511 Player::fields().team().eq("Timbers").and(
512 Player::fields()
513 .position()
514 .eq("Forward")
515 .or(Player::fields().position().eq("Goalkeeper")),
516 ),
517 )
518 .exec(&mut db)
519 .await?;
520
521 assert_eq!(2, players.len());
522 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
523 names.sort();
524 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
525
526 let players = Player::filter(
528 Player::fields().team().eq("Timbers").and(
529 Player::fields()
530 .number()
531 .eq(8)
532 .or(Player::fields().number().eq(21))
533 .or(Player::fields().number().eq(9)),
534 ),
535 )
536 .exec(&mut db)
537 .await?;
538
539 assert_eq!(3, players.len());
540 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
541 names.sort();
542 assert_eq!(names, ["Diego Chara", "Diego Valeri", "Fanendo Adi"]);
543 Ok(())
544}
545
546#[driver_test(id(ID))]
547pub async fn query_or_on_partition_key(test: &mut Test) -> Result<()> {
548 #[derive(Debug, toasty::Model)]
554 #[key(partition = team, local = name)]
555 struct Player {
556 team: String,
557
558 name: String,
559
560 #[allow(dead_code)]
561 position: String,
562 }
563
564 let mut db = test.setup_db(models!(Player)).await;
565
566 for (team, name, position) in [
567 ("Timbers", "Diego Valeri", "Midfielder"),
568 ("Timbers", "Fanendo Adi", "Forward"),
569 ("Sounders", "Clint Dempsey", "Forward"),
570 ("Sounders", "Osvaldo Alonso", "Midfielder"),
571 ("Galaxy", "Robbie Keane", "Forward"),
572 ] {
573 Player::create()
574 .team(team)
575 .name(name)
576 .position(position)
577 .exec(&mut db)
578 .await?;
579 }
580
581 let players = Player::filter(
583 Player::fields()
584 .team()
585 .eq("Timbers")
586 .or(Player::fields().team().eq("Sounders")),
587 )
588 .exec(&mut db)
589 .await?;
590
591 assert_eq!(4, players.len());
592 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
593 names.sort();
594 assert_eq!(
595 names,
596 [
597 "Clint Dempsey",
598 "Diego Valeri",
599 "Fanendo Adi",
600 "Osvaldo Alonso"
601 ]
602 );
603 Ok(())
604}
605
606#[driver_test(id(ID))]
607pub async fn query_or_on_composite_pk(test: &mut Test) -> Result<()> {
608 #[derive(Debug, toasty::Model)]
614 #[key(partition = team, local = name)]
615 struct Player {
616 team: String,
617
618 name: String,
619
620 #[allow(dead_code)]
621 position: String,
622 }
623
624 let mut db = test.setup_db(models!(Player)).await;
625
626 for (team, name, position) in [
627 ("Timbers", "Diego Valeri", "Midfielder"),
628 ("Timbers", "Fanendo Adi", "Forward"),
629 ("Sounders", "Clint Dempsey", "Forward"),
630 ("Sounders", "Osvaldo Alonso", "Midfielder"),
631 ] {
632 Player::create()
633 .team(team)
634 .name(name)
635 .position(position)
636 .exec(&mut db)
637 .await?;
638 }
639
640 let players = Player::filter(
642 Player::fields()
643 .team()
644 .eq("Timbers")
645 .and(Player::fields().name().eq("Diego Valeri"))
646 .or(Player::fields()
647 .team()
648 .eq("Sounders")
649 .and(Player::fields().name().eq("Clint Dempsey"))),
650 )
651 .exec(&mut db)
652 .await?;
653
654 assert_eq!(2, players.len());
655 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
656 names.sort();
657 assert_eq!(names, ["Clint Dempsey", "Diego Valeri"]);
658 Ok(())
659}
660
661#[driver_test(id(ID))]
662pub async fn query_or_with_comparisons(test: &mut Test) -> Result<()> {
663 #[derive(Debug, toasty::Model)]
664 #[key(partition = team, local = name)]
665 struct Player {
666 team: String,
667
668 name: String,
669
670 #[allow(dead_code)]
671 position: String,
672
673 #[allow(dead_code)]
674 number: i64,
675 }
676
677 let mut db = test.setup_db(models!(Player)).await;
678
679 for (team, name, position, number) in [
681 ("Timbers", "Diego Valeri", "Midfielder", 8),
682 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
683 ("Timbers", "Diego Chara", "Midfielder", 21),
684 ("Timbers", "Fanendo Adi", "Forward", 9),
685 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
686 ("Sounders", "Clint Dempsey", "Forward", 2),
687 ("Sounders", "Obafemi Martins", "Forward", 9),
688 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
689 ] {
690 Player::create()
691 .team(team)
692 .name(name)
693 .position(position)
694 .number(number)
695 .exec(&mut db)
696 .await?;
697 }
698
699 let players = Player::filter(
703 Player::fields().team().eq("Timbers").and(
704 Player::fields()
705 .number()
706 .gt(20)
707 .or(Player::fields().number().lt(2)),
708 ),
709 )
710 .exec(&mut db)
711 .await?;
712
713 assert_eq!(2, players.len());
714 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
715 names.sort();
716 assert_eq!(names, ["Adam Kwarasey", "Diego Chara"]);
717 Ok(())
718}
719
720#[driver_test(id(ID), requires(sql))]
721pub async fn query_arbitrary_constraint(test: &mut Test) -> Result<()> {
722 #[derive(Debug, toasty::Model)]
723 struct Event {
724 #[key]
725 #[auto]
726 id: ID,
727
728 kind: String,
729
730 timestamp: i64,
731 }
732
733 let mut db = test.setup_db(models!(Event)).await;
734
735 for (kind, ts) in [
737 ("info", 0),
738 ("warn", 1),
739 ("info", 2),
740 ("warn", 3),
741 ("info", 4),
742 ("warn", 5),
743 ("info", 6),
744 ("warn", 7),
745 ("info", 8),
746 ("warn", 9),
747 ("info", 10),
748 ("warn", 11),
749 ("info", 12),
750 ("warn", 13),
751 ("info", 14),
752 ("warn", 15),
753 ("info", 16),
754 ("warn", 17),
755 ("info", 18),
756 ("warn", 19),
757 ] {
758 Event::create()
759 .kind(kind)
760 .timestamp(ts)
761 .exec(&mut db)
762 .await?;
763 }
764
765 let events: Vec<_> = Event::filter(Event::fields().timestamp().gt(12))
766 .exec(&mut db)
767 .await?;
768
769 assert_eq_unordered!(
770 events.iter().map(|event| event.timestamp),
771 [&13, &14, &15, &16, &17, &18, &19,]
772 );
773
774 let events: Vec<_> = Event::filter(
775 Event::fields()
776 .timestamp()
777 .gt(12)
778 .and(Event::fields().kind().ne("info")),
779 )
780 .exec(&mut db)
781 .await?;
782
783 assert!(events.iter().all(|event| event.kind != "info"));
784
785 assert_eq_unordered!(
786 events.iter().map(|event| event.timestamp),
787 [&13, &15, &17, &19,]
788 );
789
790 let events: Vec<_> = Event::filter(
791 Event::fields()
792 .kind()
793 .eq("info")
794 .and(Event::fields().timestamp().ne(10)),
795 )
796 .exec(&mut db)
797 .await?;
798
799 assert_eq_unordered!(
800 events.iter().map(|event| event.timestamp),
801 [&0, &2, &4, &6, &8, &12, &14, &16, &18,]
802 );
803
804 let events: Vec<_> = Event::filter(
805 Event::fields()
806 .kind()
807 .eq("info")
808 .and(Event::fields().timestamp().gt(10)),
809 )
810 .exec(&mut db)
811 .await?;
812
813 assert_eq_unordered!(
814 events.iter().map(|event| event.timestamp),
815 [&12, &14, &16, &18,]
816 );
817
818 let events: Vec<_> = Event::filter(
819 Event::fields()
820 .kind()
821 .eq("info")
822 .and(Event::fields().timestamp().ge(10)),
823 )
824 .exec(&mut db)
825 .await?;
826
827 assert_eq_unordered!(
828 events.iter().map(|event| event.timestamp),
829 [&10, &12, &14, &16, &18,]
830 );
831
832 let events: Vec<_> = Event::filter(
833 Event::fields()
834 .kind()
835 .eq("info")
836 .and(Event::fields().timestamp().lt(10)),
837 )
838 .exec(&mut db)
839 .await?;
840
841 assert_eq_unordered!(
842 events.iter().map(|event| event.timestamp),
843 [&0, &2, &4, &6, &8]
844 );
845
846 let events: Vec<_> = Event::filter(
847 Event::fields()
848 .kind()
849 .eq("info")
850 .and(Event::fields().timestamp().le(10)),
851 )
852 .exec(&mut db)
853 .await?;
854
855 assert_eq_unordered!(
856 events.iter().map(|event| event.timestamp),
857 [&0, &2, &4, &6, &8, &10]
858 );
859 Ok(())
860}
861
862#[driver_test(id(ID))]
863pub async fn query_not_basic(test: &mut Test) -> Result<()> {
864 #[derive(Debug, toasty::Model)]
865 struct User {
866 #[key]
867 #[auto]
868 id: ID,
869
870 name: String,
871
872 #[allow(dead_code)]
873 age: i64,
874 }
875
876 let mut db = test.setup_db(models!(User)).await;
877
878 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
880 User::create().name(name).age(age).exec(&mut db).await?;
881 }
882
883 test.log().clear();
885
886 let result = User::filter(User::fields().name().eq("Alice").not())
888 .exec(&mut db)
889 .await;
890
891 if test.capability().sql {
892 let users = result?;
893 assert_eq!(3, users.len());
894 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
895 names.sort();
896 assert_eq!(names, ["Bob", "Charlie", "Diana"]);
897 } else {
898 assert!(
901 result.is_err(),
902 "Expected error for NOT query without key condition on non-SQL database"
903 );
904 }
905 Ok(())
906}
907
908#[driver_test(id(ID))]
909pub async fn query_not_and_combined(test: &mut Test) -> Result<()> {
910 #[derive(Debug, toasty::Model)]
911 struct User {
912 #[key]
913 #[auto]
914 id: ID,
915
916 name: String,
917
918 #[allow(dead_code)]
919 age: i64,
920
921 #[allow(dead_code)]
922 active: bool,
923 }
924
925 let mut db = test.setup_db(models!(User)).await;
926
927 for (name, age, active) in [
929 ("Alice", 25, true),
930 ("Bob", 30, false),
931 ("Charlie", 35, true),
932 ("Diana", 40, false),
933 ("Eve", 25, false),
934 ] {
935 User::create()
936 .name(name)
937 .age(age)
938 .active(active)
939 .exec(&mut db)
940 .await?;
941 }
942
943 let result = User::filter(
946 User::fields()
947 .active()
948 .eq(true)
949 .and(User::fields().age().eq(25).not()),
950 )
951 .exec(&mut db)
952 .await;
953
954 if test.capability().sql {
955 let users = result?;
956 assert_eq!(1, users.len());
957 assert_eq!("Charlie", users[0].name);
958 } else {
959 assert!(
960 result.is_err(),
961 "Expected error for NOT query without key condition on non-SQL database"
962 );
963 }
964 Ok(())
965}
966
967#[driver_test(id(ID))]
968pub async fn query_not_or_combined(test: &mut Test) -> Result<()> {
969 #[derive(Debug, toasty::Model)]
970 struct User {
971 #[key]
972 #[auto]
973 id: ID,
974
975 name: String,
976
977 #[allow(dead_code)]
978 age: i64,
979 }
980
981 let mut db = test.setup_db(models!(User)).await;
982
983 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
985 User::create().name(name).age(age).exec(&mut db).await?;
986 }
987
988 let result = User::filter(
991 User::fields()
992 .name()
993 .eq("Alice")
994 .or(User::fields().name().eq("Bob"))
995 .not(),
996 )
997 .exec(&mut db)
998 .await;
999
1000 if test.capability().sql {
1001 let users = result?;
1002 assert_eq!(2, users.len());
1003 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
1004 names.sort();
1005 assert_eq!(names, ["Charlie", "Diana"]);
1006 } else {
1007 assert!(
1008 result.is_err(),
1009 "Expected error for NOT query without key condition on non-SQL database"
1010 );
1011 }
1012 Ok(())
1013}
1014
1015#[driver_test(id(ID))]
1016pub async fn query_not_with_index(test: &mut Test) -> Result<()> {
1017 #[derive(Debug, toasty::Model)]
1018 #[key(partition = team, local = name)]
1019 struct Player {
1020 team: String,
1021
1022 name: String,
1023
1024 #[allow(dead_code)]
1025 position: String,
1026
1027 #[allow(dead_code)]
1028 number: i64,
1029 }
1030
1031 let mut db = test.setup_db(models!(Player)).await;
1032
1033 for (team, name, position, number) in [
1035 ("Timbers", "Diego Valeri", "Midfielder", 8),
1036 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1037 ("Timbers", "Diego Chara", "Midfielder", 21),
1038 ("Timbers", "Fanendo Adi", "Forward", 9),
1039 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1040 ("Sounders", "Clint Dempsey", "Forward", 2),
1041 ("Sounders", "Obafemi Martins", "Forward", 9),
1042 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
1043 ] {
1044 Player::create()
1045 .team(team)
1046 .name(name)
1047 .position(position)
1048 .number(number)
1049 .exec(&mut db)
1050 .await?;
1051 }
1052
1053 let players = Player::filter(
1057 Player::fields()
1058 .team()
1059 .eq("Timbers")
1060 .and(Player::fields().position().eq("Midfielder").not()),
1061 )
1062 .exec(&mut db)
1063 .await?;
1064
1065 assert_eq!(2, players.len());
1066 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1067 names.sort();
1068 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1069
1070 let players = Player::filter(
1074 Player::fields()
1075 .team()
1076 .eq("Timbers")
1077 .and(Player::fields().number().gt(8).not()),
1078 )
1079 .exec(&mut db)
1080 .await?;
1081
1082 assert_eq!(3, players.len());
1083 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1084 names.sort();
1085 assert_eq!(names, ["Adam Kwarasey", "Darlington Nagbe", "Diego Valeri"]);
1086 Ok(())
1087}
1088
1089#[driver_test(id(ID))]
1090pub async fn query_not_operator_syntax(test: &mut Test) -> Result<()> {
1091 #[derive(Debug, toasty::Model)]
1092 #[key(partition = team, local = name)]
1093 struct Player {
1094 team: String,
1095
1096 name: String,
1097
1098 #[allow(dead_code)]
1099 position: String,
1100
1101 #[allow(dead_code)]
1102 number: i64,
1103 }
1104
1105 let mut db = test.setup_db(models!(Player)).await;
1106
1107 for (team, name, position, number) in [
1108 ("Timbers", "Diego Valeri", "Midfielder", 8),
1109 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1110 ("Timbers", "Diego Chara", "Midfielder", 21),
1111 ("Timbers", "Fanendo Adi", "Forward", 9),
1112 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1113 ] {
1114 Player::create()
1115 .team(team)
1116 .name(name)
1117 .position(position)
1118 .number(number)
1119 .exec(&mut db)
1120 .await?;
1121 }
1122
1123 let players = Player::filter(
1126 Player::fields()
1127 .team()
1128 .eq("Timbers")
1129 .and(!Player::fields().position().eq("Midfielder")),
1130 )
1131 .exec(&mut db)
1132 .await?;
1133
1134 assert_eq!(2, players.len());
1135 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1136 names.sort();
1137 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1138
1139 let players = Player::filter(
1141 Player::fields().team().eq("Timbers").and(
1142 !(Player::fields()
1143 .number()
1144 .gt(8)
1145 .or(Player::fields().position().eq("Goalkeeper"))),
1146 ),
1147 )
1148 .exec(&mut db)
1149 .await?;
1150
1151 assert_eq!(2, players.len());
1154 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1155 names.sort();
1156 assert_eq!(names, ["Darlington Nagbe", "Diego Valeri"]);
1157 Ok(())
1158}