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 if test.capability().scan {
342 let users = result?;
343 assert_eq!(2, users.len());
344 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
345 names.sort();
346 assert_eq!(names, ["Alice", "Charlie"]);
347 } else {
348 assert!(
349 result.is_err(),
350 "Expected error for OR query without key condition on non-SQL database"
351 );
352 }
353 Ok(())
354}
355
356#[driver_test(id(ID))]
357pub async fn query_or_multiple(test: &mut Test) -> Result<()> {
358 #[derive(Debug, toasty::Model)]
359 struct User {
360 #[key]
361 #[auto]
362 id: ID,
363
364 name: String,
365
366 #[allow(dead_code)]
367 age: i64,
368 }
369
370 let mut db = test.setup_db(models!(User)).await;
371
372 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
374 User::create().name(name).age(age).exec(&mut db).await?;
375 }
376
377 let result = User::filter(
379 User::fields()
380 .name()
381 .eq("Alice")
382 .or(User::fields().age().eq(35))
383 .or(User::fields().age().eq(40)),
384 )
385 .exec(&mut db)
386 .await;
387
388 if test.capability().sql || test.capability().scan {
389 let users = result?;
390 assert_eq!(3, users.len());
391 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
392 names.sort();
393 assert_eq!(names, ["Alice", "Charlie", "Diana"]);
394 } else {
395 assert!(
396 result.is_err(),
397 "Expected error for OR query without key condition on non-SQL database"
398 );
399 }
400 Ok(())
401}
402
403#[driver_test(id(ID))]
404pub async fn query_or_and_combined(test: &mut Test) -> Result<()> {
405 #[derive(Debug, toasty::Model)]
406 struct User {
407 #[key]
408 #[auto]
409 id: ID,
410
411 name: String,
412
413 #[allow(dead_code)]
414 age: i64,
415
416 #[allow(dead_code)]
417 active: bool,
418 }
419
420 let mut db = test.setup_db(models!(User)).await;
421
422 for (name, age, active) in [
424 ("Alice", 25, true),
425 ("Bob", 30, false),
426 ("Charlie", 35, true),
427 ("Diana", 40, false),
428 ("Eve", 25, false),
429 ] {
430 User::create()
431 .name(name)
432 .age(age)
433 .active(active)
434 .exec(&mut db)
435 .await?;
436 }
437
438 let result = User::filter(
440 User::fields()
441 .name()
442 .eq("Alice")
443 .or(User::fields().age().eq(35))
444 .and(User::fields().active().eq(true)),
445 )
446 .exec(&mut db)
447 .await;
448
449 if test.capability().sql || test.capability().scan {
450 let users = result?;
451 assert_eq!(2, users.len());
452 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
453 names.sort();
454 assert_eq!(names, ["Alice", "Charlie"]);
455 } else {
456 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(scan))]
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 || test.capability().scan {
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!(
893 result.is_err(),
894 "Expected error for NOT query without key condition on non-SQL database"
895 );
896 }
897 Ok(())
898}
899
900#[driver_test(id(ID))]
901pub async fn query_not_and_combined(test: &mut Test) -> Result<()> {
902 #[derive(Debug, toasty::Model)]
903 struct User {
904 #[key]
905 #[auto]
906 id: ID,
907
908 name: String,
909
910 #[allow(dead_code)]
911 age: i64,
912
913 #[allow(dead_code)]
914 active: bool,
915 }
916
917 let mut db = test.setup_db(models!(User)).await;
918
919 for (name, age, active) in [
921 ("Alice", 25, true),
922 ("Bob", 30, false),
923 ("Charlie", 35, true),
924 ("Diana", 40, false),
925 ("Eve", 25, false),
926 ] {
927 User::create()
928 .name(name)
929 .age(age)
930 .active(active)
931 .exec(&mut db)
932 .await?;
933 }
934
935 let result = User::filter(
938 User::fields()
939 .active()
940 .eq(true)
941 .and(User::fields().age().eq(25).not()),
942 )
943 .exec(&mut db)
944 .await;
945
946 if test.capability().sql || test.capability().scan {
947 let users = result?;
948 assert_eq!(1, users.len());
949 assert_eq!("Charlie", users[0].name);
950 } else {
951 assert!(
952 result.is_err(),
953 "Expected error for NOT query without key condition on non-SQL database"
954 );
955 }
956 Ok(())
957}
958
959#[driver_test(id(ID))]
960pub async fn query_not_or_combined(test: &mut Test) -> Result<()> {
961 #[derive(Debug, toasty::Model)]
962 struct User {
963 #[key]
964 #[auto]
965 id: ID,
966
967 name: String,
968
969 #[allow(dead_code)]
970 age: i64,
971 }
972
973 let mut db = test.setup_db(models!(User)).await;
974
975 for (name, age) in [("Alice", 25), ("Bob", 30), ("Charlie", 35), ("Diana", 40)] {
977 User::create().name(name).age(age).exec(&mut db).await?;
978 }
979
980 let result = User::filter(
983 User::fields()
984 .name()
985 .eq("Alice")
986 .or(User::fields().name().eq("Bob"))
987 .not(),
988 )
989 .exec(&mut db)
990 .await;
991
992 if test.capability().sql || test.capability().scan {
993 let users = result?;
994 assert_eq!(2, users.len());
995 let mut names: Vec<_> = users.iter().map(|u| u.name.as_str()).collect();
996 names.sort();
997 assert_eq!(names, ["Charlie", "Diana"]);
998 } else {
999 assert!(
1000 result.is_err(),
1001 "Expected error for NOT query without key condition on non-SQL database"
1002 );
1003 }
1004 Ok(())
1005}
1006
1007#[driver_test(id(ID))]
1008pub async fn query_not_with_index(test: &mut Test) -> Result<()> {
1009 #[derive(Debug, toasty::Model)]
1010 #[key(partition = team, local = name)]
1011 struct Player {
1012 team: String,
1013
1014 name: String,
1015
1016 #[allow(dead_code)]
1017 position: String,
1018
1019 #[allow(dead_code)]
1020 number: i64,
1021 }
1022
1023 let mut db = test.setup_db(models!(Player)).await;
1024
1025 for (team, name, position, number) in [
1027 ("Timbers", "Diego Valeri", "Midfielder", 8),
1028 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1029 ("Timbers", "Diego Chara", "Midfielder", 21),
1030 ("Timbers", "Fanendo Adi", "Forward", 9),
1031 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1032 ("Sounders", "Clint Dempsey", "Forward", 2),
1033 ("Sounders", "Obafemi Martins", "Forward", 9),
1034 ("Sounders", "Osvaldo Alonso", "Midfielder", 6),
1035 ] {
1036 Player::create()
1037 .team(team)
1038 .name(name)
1039 .position(position)
1040 .number(number)
1041 .exec(&mut db)
1042 .await?;
1043 }
1044
1045 let players = Player::filter(
1049 Player::fields()
1050 .team()
1051 .eq("Timbers")
1052 .and(Player::fields().position().eq("Midfielder").not()),
1053 )
1054 .exec(&mut db)
1055 .await?;
1056
1057 assert_eq!(2, players.len());
1058 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1059 names.sort();
1060 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1061
1062 let players = Player::filter(
1066 Player::fields()
1067 .team()
1068 .eq("Timbers")
1069 .and(Player::fields().number().gt(8).not()),
1070 )
1071 .exec(&mut db)
1072 .await?;
1073
1074 assert_eq!(3, players.len());
1075 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1076 names.sort();
1077 assert_eq!(names, ["Adam Kwarasey", "Darlington Nagbe", "Diego Valeri"]);
1078 Ok(())
1079}
1080
1081#[driver_test(id(ID))]
1082pub async fn query_not_operator_syntax(test: &mut Test) -> Result<()> {
1083 #[derive(Debug, toasty::Model)]
1084 #[key(partition = team, local = name)]
1085 struct Player {
1086 team: String,
1087
1088 name: String,
1089
1090 #[allow(dead_code)]
1091 position: String,
1092
1093 #[allow(dead_code)]
1094 number: i64,
1095 }
1096
1097 let mut db = test.setup_db(models!(Player)).await;
1098
1099 for (team, name, position, number) in [
1100 ("Timbers", "Diego Valeri", "Midfielder", 8),
1101 ("Timbers", "Darlington Nagbe", "Midfielder", 6),
1102 ("Timbers", "Diego Chara", "Midfielder", 21),
1103 ("Timbers", "Fanendo Adi", "Forward", 9),
1104 ("Timbers", "Adam Kwarasey", "Goalkeeper", 1),
1105 ] {
1106 Player::create()
1107 .team(team)
1108 .name(name)
1109 .position(position)
1110 .number(number)
1111 .exec(&mut db)
1112 .await?;
1113 }
1114
1115 let players = Player::filter(
1118 Player::fields()
1119 .team()
1120 .eq("Timbers")
1121 .and(!Player::fields().position().eq("Midfielder")),
1122 )
1123 .exec(&mut db)
1124 .await?;
1125
1126 assert_eq!(2, players.len());
1127 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1128 names.sort();
1129 assert_eq!(names, ["Adam Kwarasey", "Fanendo Adi"]);
1130
1131 let players = Player::filter(
1133 Player::fields().team().eq("Timbers").and(
1134 !(Player::fields()
1135 .number()
1136 .gt(8)
1137 .or(Player::fields().position().eq("Goalkeeper"))),
1138 ),
1139 )
1140 .exec(&mut db)
1141 .await?;
1142
1143 assert_eq!(2, players.len());
1146 let mut names: Vec<_> = players.iter().map(|p| p.name.as_str()).collect();
1147 names.sort();
1148 assert_eq!(names, ["Darlington Nagbe", "Diego Valeri"]);
1149 Ok(())
1150}