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 })),
338 }),
339 }),
340 }));
341 } else {
342 assert!(
345 result.is_err(),
346 "Expected error for OR query without key condition on non-SQL database"
347 );
348 }
349 Ok(())
350}
351
352#[driver_test(id(ID))]
353pub async fn query_or_multiple(test: &mut Test) -> Result<()> {
354 #[derive(Debug, toasty::Model)]
355 struct User {
356 #[key]
357 #[auto]
358 id: ID,
359
360 name: String,
361
362 #[allow(dead_code)]
363 age: i64,
364 }
365
366 let mut db = test.setup_db(models!(User)).await;
367
368 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
370 User::create().name(name).age(age).exec(&mut db).await?;
371 }
372
373 let result = User::filter(
375 User::fields()
376 .name()
377 .eq("Alice")
378 .or(User::fields().age().eq(35))
379 .or(User::fields().age().eq(40)),
380 )
381 .exec(&mut db)
382 .await;
383
384 if test.capability().sql {
385 let users = result?;
386 assert_eq!(3, users.len());
387 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
388 names.sort();
389 assert_eq!(names, ["Alice", "Charlie", "Diana"]);
390 } else {
391 assert!(
394 result.is_err(),
395 "Expected error for OR query without key condition on non-SQL database"
396 );
397 }
398 Ok(())
399}
400
401#[driver_test(id(ID))]
402pub async fn query_or_and_combined(test: &mut Test) -> Result<()> {
403 #[derive(Debug, toasty::Model)]
404 struct User {
405 #[key]
406 #[auto]
407 id: ID,
408
409 name: String,
410
411 #[allow(dead_code)]
412 age: i64,
413
414 #[allow(dead_code)]
415 active: bool,
416 }
417
418 let mut db = test.setup_db(models!(User)).await;
419
420 for (name, age, active) in [
422 ("Alice", 25, true),
423 ("Bob", 30, false),
424 ("Charlie", 35, true),
425 ("Diana", 40, false),
426 ("Eve", 25, false),
427 ] {
428 User::create()
429 .name(name)
430 .age(age)
431 .active(active)
432 .exec(&mut db)
433 .await?;
434 }
435
436 let result = User::filter(
438 User::fields()
439 .name()
440 .eq("Alice")
441 .or(User::fields().age().eq(35))
442 .and(User::fields().active().eq(true)),
443 )
444 .exec(&mut db)
445 .await;
446
447 if test.capability().sql {
448 let users = result?;
449 assert_eq!(2, users.len());
450 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
451 names.sort();
452 assert_eq!(names, ["Alice", "Charlie"]);
453 } else {
454 assert!(
457 result.is_err(),
458 "Expected error for OR query without key condition on non-SQL database"
459 );
460 }
461 Ok(())
462}
463
464#[driver_test(id(ID))]
465pub async fn query_or_with_index(test: &mut Test) -> Result<()> {
466 #[derive(Debug, toasty::Model)]
467 #[key(partition = team, local = name)]
468 struct Player {
469 team: String,
470
471 name: String,
472
473 #[allow(dead_code)]
474 position: String,
475
476 #[allow(dead_code)]
477 number: i64,
478 }
479
480 let mut db = test.setup_db(models!(Player)).await;
481
482 for (team, name, position, number) in [
484 ("Timbers", "Diego Valeri", "Midfielder", 8),
485 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
486 ("Timbers", "Diego Chara", "Midfielder", 21),
487 ("Timbers", "Fanendo Adi", "Forward", 9),
488 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
489 ("Sounders", "Clint Dempsey", "Forward", 2),
490 ("Sounders", "Obafemi Martins", "Forward", 9),
491 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
492 ] {
493 Player::create()
494 .team(team)
495 .name(name)
496 .position(position)
497 .number(number)
498 .exec(&mut db)
499 .await?;
500 }
501
502 let players = Player::filter(
505 Player::fields().team().eq("Timbers").and(
506 Player::fields()
507 .position()
508 .eq("Forward")
509 .or(Player::fields().position().eq("Goalkeeper")),
510 ),
511 )
512 .exec(&mut db)
513 .await?;
514
515 assert_eq!(2, players.len());
516 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
517 names.sort();
518 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
519
520 let players = Player::filter(
522 Player::fields().team().eq("Timbers").and(
523 Player::fields()
524 .number()
525 .eq(8)
526 .or(Player::fields().number().eq(21))
527 .or(Player::fields().number().eq(9)),
528 ),
529 )
530 .exec(&mut db)
531 .await?;
532
533 assert_eq!(3, players.len());
534 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
535 names.sort();
536 assert_eq!(names, ["Diego Chara", "Diego Valeri", "Fanendo Adi"]);
537 Ok(())
538}
539
540#[driver_test(id(ID))]
541pub async fn query_or_on_partition_key(test: &mut Test) -> Result<()> {
542 #[derive(Debug, toasty::Model)]
548 #[key(partition = team, local = name)]
549 struct Player {
550 team: String,
551
552 name: String,
553
554 #[allow(dead_code)]
555 position: String,
556 }
557
558 let mut db = test.setup_db(models!(Player)).await;
559
560 for (team, name, position) in [
561 ("Timbers", "Diego Valeri", "Midfielder"),
562 ("Timbers", "Fanendo Adi", "Forward"),
563 ("Sounders", "Clint Dempsey", "Forward"),
564 ("Sounders", "Osvaldo Alonso", "Midfielder"),
565 ("Galaxy", "Robbie Keane", "Forward"),
566 ] {
567 Player::create()
568 .team(team)
569 .name(name)
570 .position(position)
571 .exec(&mut db)
572 .await?;
573 }
574
575 let players = Player::filter(
577 Player::fields()
578 .team()
579 .eq("Timbers")
580 .or(Player::fields().team().eq("Sounders")),
581 )
582 .exec(&mut db)
583 .await?;
584
585 assert_eq!(4, players.len());
586 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
587 names.sort();
588 assert_eq!(
589 names,
590 [
591 "Clint Dempsey",
592 "Diego Valeri",
593 "Fanendo Adi",
594 "Osvaldo Alonso"
595 ]
596 );
597 Ok(())
598}
599
600#[driver_test(id(ID))]
601pub async fn query_or_on_composite_pk(test: &mut Test) -> Result<()> {
602 #[derive(Debug, toasty::Model)]
608 #[key(partition = team, local = name)]
609 struct Player {
610 team: String,
611
612 name: String,
613
614 #[allow(dead_code)]
615 position: String,
616 }
617
618 let mut db = test.setup_db(models!(Player)).await;
619
620 for (team, name, position) in [
621 ("Timbers", "Diego Valeri", "Midfielder"),
622 ("Timbers", "Fanendo Adi", "Forward"),
623 ("Sounders", "Clint Dempsey", "Forward"),
624 ("Sounders", "Osvaldo Alonso", "Midfielder"),
625 ] {
626 Player::create()
627 .team(team)
628 .name(name)
629 .position(position)
630 .exec(&mut db)
631 .await?;
632 }
633
634 let players = Player::filter(
636 Player::fields()
637 .team()
638 .eq("Timbers")
639 .and(Player::fields().name().eq("Diego Valeri"))
640 .or(Player::fields()
641 .team()
642 .eq("Sounders")
643 .and(Player::fields().name().eq("Clint Dempsey"))),
644 )
645 .exec(&mut db)
646 .await?;
647
648 assert_eq!(2, players.len());
649 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
650 names.sort();
651 assert_eq!(names, ["Clint Dempsey", "Diego Valeri"]);
652 Ok(())
653}
654
655#[driver_test(id(ID))]
656pub async fn query_or_with_comparisons(test: &mut Test) -> Result<()> {
657 #[derive(Debug, toasty::Model)]
658 #[key(partition = team, local = name)]
659 struct Player {
660 team: String,
661
662 name: String,
663
664 #[allow(dead_code)]
665 position: String,
666
667 #[allow(dead_code)]
668 number: i64,
669 }
670
671 let mut db = test.setup_db(models!(Player)).await;
672
673 for (team, name, position, number) in [
675 ("Timbers", "Diego Valeri", "Midfielder", 8),
676 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
677 ("Timbers", "Diego Chara", "Midfielder", 21),
678 ("Timbers", "Fanendo Adi", "Forward", 9),
679 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
680 ("Sounders", "Clint Dempsey", "Forward", 2),
681 ("Sounders", "Obafemi Martins", "Forward", 9),
682 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
683 ] {
684 Player::create()
685 .team(team)
686 .name(name)
687 .position(position)
688 .number(number)
689 .exec(&mut db)
690 .await?;
691 }
692
693 let players = Player::filter(
697 Player::fields().team().eq("Timbers").and(
698 Player::fields()
699 .number()
700 .gt(20)
701 .or(Player::fields().number().lt(2)),
702 ),
703 )
704 .exec(&mut db)
705 .await?;
706
707 assert_eq!(2, players.len());
708 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
709 names.sort();
710 assert_eq!(names, ["Adam Kwarasey", "Diego Chara"]);
711 Ok(())
712}
713
714#[driver_test(id(ID), requires(sql))]
715pub async fn query_arbitrary_constraint(test: &mut Test) -> Result<()> {
716 #[derive(Debug, toasty::Model)]
717 struct Event {
718 #[key]
719 #[auto]
720 id: ID,
721
722 kind: String,
723
724 timestamp: i64,
725 }
726
727 let mut db = test.setup_db(models!(Event)).await;
728
729 for (kind, ts) in [
731 ("info", 0),
732 ("warn", 1),
733 ("info", 2),
734 ("warn", 3),
735 ("info", 4),
736 ("warn", 5),
737 ("info", 6),
738 ("warn", 7),
739 ("info", 8),
740 ("warn", 9),
741 ("info", 10),
742 ("warn", 11),
743 ("info", 12),
744 ("warn", 13),
745 ("info", 14),
746 ("warn", 15),
747 ("info", 16),
748 ("warn", 17),
749 ("info", 18),
750 ("warn", 19),
751 ] {
752 Event::create()
753 .kind(kind)
754 .timestamp(ts)
755 .exec(&mut db)
756 .await?;
757 }
758
759 let events: Vec<_> = Event::filter(Event::fields().timestamp().gt(12))
760 .exec(&mut db)
761 .await?;
762
763 assert_eq_unordered!(
764 events.iter().map(|event| event.timestamp),
765 [&13, &14, &15, &16, &17, &18, &19,]
766 );
767
768 let events: Vec<_> = Event::filter(
769 Event::fields()
770 .timestamp()
771 .gt(12)
772 .and(Event::fields().kind().ne("info")),
773 )
774 .exec(&mut db)
775 .await?;
776
777 assert!(events.iter().all(|event| event.kind != "info"));
778
779 assert_eq_unordered!(
780 events.iter().map(|event| event.timestamp),
781 [&13, &15, &17, &19,]
782 );
783
784 let events: Vec<_> = Event::filter(
785 Event::fields()
786 .kind()
787 .eq("info")
788 .and(Event::fields().timestamp().ne(10)),
789 )
790 .exec(&mut db)
791 .await?;
792
793 assert_eq_unordered!(
794 events.iter().map(|event| event.timestamp),
795 [&0, &2, &4, &6, &8, &12, &14, &16, &18,]
796 );
797
798 let events: Vec<_> = Event::filter(
799 Event::fields()
800 .kind()
801 .eq("info")
802 .and(Event::fields().timestamp().gt(10)),
803 )
804 .exec(&mut db)
805 .await?;
806
807 assert_eq_unordered!(
808 events.iter().map(|event| event.timestamp),
809 [&12, &14, &16, &18,]
810 );
811
812 let events: Vec<_> = Event::filter(
813 Event::fields()
814 .kind()
815 .eq("info")
816 .and(Event::fields().timestamp().ge(10)),
817 )
818 .exec(&mut db)
819 .await?;
820
821 assert_eq_unordered!(
822 events.iter().map(|event| event.timestamp),
823 [&10, &12, &14, &16, &18,]
824 );
825
826 let events: Vec<_> = Event::filter(
827 Event::fields()
828 .kind()
829 .eq("info")
830 .and(Event::fields().timestamp().lt(10)),
831 )
832 .exec(&mut db)
833 .await?;
834
835 assert_eq_unordered!(
836 events.iter().map(|event| event.timestamp),
837 [&0, &2, &4, &6, &8]
838 );
839
840 let events: Vec<_> = Event::filter(
841 Event::fields()
842 .kind()
843 .eq("info")
844 .and(Event::fields().timestamp().le(10)),
845 )
846 .exec(&mut db)
847 .await?;
848
849 assert_eq_unordered!(
850 events.iter().map(|event| event.timestamp),
851 [&0, &2, &4, &6, &8, &10]
852 );
853 Ok(())
854}
855
856#[driver_test(id(ID))]
857pub async fn query_not_basic(test: &mut Test) -> Result<()> {
858 #[derive(Debug, toasty::Model)]
859 struct User {
860 #[key]
861 #[auto]
862 id: ID,
863
864 name: String,
865
866 #[allow(dead_code)]
867 age: i64,
868 }
869
870 let mut db = test.setup_db(models!(User)).await;
871
872 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
874 User::create().name(name).age(age).exec(&mut db).await?;
875 }
876
877 test.log().clear();
879
880 let result = User::filter(User::fields().name().eq("Alice").not())
882 .exec(&mut db)
883 .await;
884
885 if test.capability().sql {
886 let users = result?;
887 assert_eq!(3, users.len());
888 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
889 names.sort();
890 assert_eq!(names, ["Bob", "Charlie", "Diana"]);
891 } else {
892 assert!(
895 result.is_err(),
896 "Expected error for NOT query without key condition on non-SQL database"
897 );
898 }
899 Ok(())
900}
901
902#[driver_test(id(ID))]
903pub async fn query_not_and_combined(test: &mut Test) -> Result<()> {
904 #[derive(Debug, toasty::Model)]
905 struct User {
906 #[key]
907 #[auto]
908 id: ID,
909
910 name: String,
911
912 #[allow(dead_code)]
913 age: i64,
914
915 #[allow(dead_code)]
916 active: bool,
917 }
918
919 let mut db = test.setup_db(models!(User)).await;
920
921 for (name, age, active) in [
923 ("Alice", 25, true),
924 ("Bob", 30, false),
925 ("Charlie", 35, true),
926 ("Diana", 40, false),
927 ("Eve", 25, false),
928 ] {
929 User::create()
930 .name(name)
931 .age(age)
932 .active(active)
933 .exec(&mut db)
934 .await?;
935 }
936
937 let result = User::filter(
940 User::fields()
941 .active()
942 .eq(true)
943 .and(User::fields().age().eq(25).not()),
944 )
945 .exec(&mut db)
946 .await;
947
948 if test.capability().sql {
949 let users = result?;
950 assert_eq!(1, users.len());
951 assert_eq!("Charlie", users[0].name);
952 } else {
953 assert!(
954 result.is_err(),
955 "Expected error for NOT query without key condition on non-SQL database"
956 );
957 }
958 Ok(())
959}
960
961#[driver_test(id(ID))]
962pub async fn query_not_or_combined(test: &mut Test) -> Result<()> {
963 #[derive(Debug, toasty::Model)]
964 struct User {
965 #[key]
966 #[auto]
967 id: ID,
968
969 name: String,
970
971 #[allow(dead_code)]
972 age: i64,
973 }
974
975 let mut db = test.setup_db(models!(User)).await;
976
977 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
979 User::create().name(name).age(age).exec(&mut db).await?;
980 }
981
982 let result = User::filter(
985 User::fields()
986 .name()
987 .eq("Alice")
988 .or(User::fields().name().eq("Bob"))
989 .not(),
990 )
991 .exec(&mut db)
992 .await;
993
994 if test.capability().sql {
995 let users = result?;
996 assert_eq!(2, users.len());
997 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
998 names.sort();
999 assert_eq!(names, ["Charlie", "Diana"]);
1000 } else {
1001 assert!(
1002 result.is_err(),
1003 "Expected error for NOT query without key condition on non-SQL database"
1004 );
1005 }
1006 Ok(())
1007}
1008
1009#[driver_test(id(ID))]
1010pub async fn query_not_with_index(test: &mut Test) -> Result<()> {
1011 #[derive(Debug, toasty::Model)]
1012 #[key(partition = team, local = name)]
1013 struct Player {
1014 team: String,
1015
1016 name: String,
1017
1018 #[allow(dead_code)]
1019 position: String,
1020
1021 #[allow(dead_code)]
1022 number: i64,
1023 }
1024
1025 let mut db = test.setup_db(models!(Player)).await;
1026
1027 for (team, name, position, number) in [
1029 ("Timbers", "Diego Valeri", "Midfielder", 8),
1030 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1031 ("Timbers", "Diego Chara", "Midfielder", 21),
1032 ("Timbers", "Fanendo Adi", "Forward", 9),
1033 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1034 ("Sounders", "Clint Dempsey", "Forward", 2),
1035 ("Sounders", "Obafemi Martins", "Forward", 9),
1036 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
1037 ] {
1038 Player::create()
1039 .team(team)
1040 .name(name)
1041 .position(position)
1042 .number(number)
1043 .exec(&mut db)
1044 .await?;
1045 }
1046
1047 let players = Player::filter(
1051 Player::fields()
1052 .team()
1053 .eq("Timbers")
1054 .and(Player::fields().position().eq("Midfielder").not()),
1055 )
1056 .exec(&mut db)
1057 .await?;
1058
1059 assert_eq!(2, players.len());
1060 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1061 names.sort();
1062 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1063
1064 let players = Player::filter(
1068 Player::fields()
1069 .team()
1070 .eq("Timbers")
1071 .and(Player::fields().number().gt(8).not()),
1072 )
1073 .exec(&mut db)
1074 .await?;
1075
1076 assert_eq!(3, players.len());
1077 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1078 names.sort();
1079 assert_eq!(names, ["Adam Kwarasey", "Darlington Nagbe", "Diego Valeri"]);
1080 Ok(())
1081}
1082
1083#[driver_test(id(ID))]
1084pub async fn query_not_operator_syntax(test: &mut Test) -> Result<()> {
1085 #[derive(Debug, toasty::Model)]
1086 #[key(partition = team, local = name)]
1087 struct Player {
1088 team: String,
1089
1090 name: String,
1091
1092 #[allow(dead_code)]
1093 position: String,
1094
1095 #[allow(dead_code)]
1096 number: i64,
1097 }
1098
1099 let mut db = test.setup_db(models!(Player)).await;
1100
1101 for (team, name, position, number) in [
1102 ("Timbers", "Diego Valeri", "Midfielder", 8),
1103 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1104 ("Timbers", "Diego Chara", "Midfielder", 21),
1105 ("Timbers", "Fanendo Adi", "Forward", 9),
1106 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1107 ] {
1108 Player::create()
1109 .team(team)
1110 .name(name)
1111 .position(position)
1112 .number(number)
1113 .exec(&mut db)
1114 .await?;
1115 }
1116
1117 let players = Player::filter(
1120 Player::fields()
1121 .team()
1122 .eq("Timbers")
1123 .and(!Player::fields().position().eq("Midfielder")),
1124 )
1125 .exec(&mut db)
1126 .await?;
1127
1128 assert_eq!(2, players.len());
1129 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1130 names.sort();
1131 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1132
1133 let players = Player::filter(
1135 Player::fields().team().eq("Timbers").and(
1136 !(Player::fields()
1137 .number()
1138 .gt(8)
1139 .or(Player::fields().position().eq("Goalkeeper"))),
1140 ),
1141 )
1142 .exec(&mut db)
1143 .await?;
1144
1145 assert_eq!(2, players.len());
1148 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1149 names.sort();
1150 assert_eq!(names, ["Darlington Nagbe", "Diego Valeri"]);
1151 Ok(())
1152}