1use std::sync::LazyLock;
2use tank::{
3 Entity, Executor, expr,
4 stream::{StreamExt, TryStreamExt},
5};
6use tokio::sync::Mutex;
7
8static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
9
10#[derive(Entity, Debug, PartialEq)]
11#[tank(schema = "testing", name = "conditions")]
12struct ConditionEntry {
13 #[tank(primary_key)]
14 id: i32,
15 name: Option<String>,
16 active: bool,
17 verified: Option<bool>,
18}
19
20pub async fn conditions(executor: &mut impl Executor) {
21 let _lock = MUTEX.lock().await;
22
23 ConditionEntry::drop_table(executor, true, false)
25 .await
26 .expect("Failed to drop ConditionEntry table");
27 ConditionEntry::create_table(executor, true, true)
28 .await
29 .expect("Failed to create ConditionEntry table");
30
31 let entries = vec![
33 ConditionEntry {
34 id: 1,
35 name: Some("Alice".into()),
36 active: true,
37 verified: Some(true),
38 },
39 ConditionEntry {
40 id: 2,
41 name: Some("Bob".into()),
42 active: false,
43 verified: Some(false),
44 },
45 ConditionEntry {
46 id: 3,
47 name: None,
48 active: true,
49 verified: None,
50 },
51 ConditionEntry {
52 id: 4,
53 name: Some("Charlie".into()),
54 active: true,
55 verified: Some(true),
56 },
57 ];
58 ConditionEntry::insert_many(executor, &entries)
59 .await
60 .expect("Failed to insert entries");
61
62 let count = ConditionEntry::find_many(executor, expr!(name != NULL), None)
63 .map_err(|e| panic!("{e:#}"))
64 .count()
65 .await;
66 assert_eq!(count, 3, "Should find 3 entries where `name IS NOT NULL`");
67
68 let count = ConditionEntry::find_many(executor, expr!(name == NULL), None)
69 .map_err(|e| panic!("{e:#}"))
70 .count()
71 .await;
72 assert_eq!(count, 1, "Should find 1 entry where `name IS NULL`");
73
74 let count = ConditionEntry::find_many(executor, expr!(id == (1, 3, 5) as IN), None)
75 .map_err(|e| panic!("{e:#}"))
76 .count()
77 .await;
78 assert_eq!(count, 2, "Should find 2 entries with `id IN (1, 3, 5)`");
79
80 let count = ConditionEntry::find_many(executor, expr!(!active), None)
81 .map_err(|e| panic!("{e:#}"))
82 .count()
83 .await;
84 assert_eq!(count, 1, "Should find 1 inactive entry");
85
86 let count = ConditionEntry::find_many(executor, expr!(id > 3 && active == true), None)
87 .map_err(|e| panic!("{e:#}"))
88 .count()
89 .await;
90 assert_eq!(count, 1, "Should find 1 entry with `id > 3` and active");
91
92 let count =
93 ConditionEntry::find_many(executor, expr!(ConditionEntry::name == "%e" as LIKE), None)
94 .map_err(|e| panic!("{e:#}"))
95 .count()
96 .await;
97 assert_eq!(count, 2, "Should find 2 entry with `name LIKE '%e'`");
98
99 let count =
100 ConditionEntry::find_many(executor, expr!(ConditionEntry::name != "%e" as LIKE), None)
101 .map_err(|e| panic!("{e:#}"))
102 .count()
103 .await;
104 assert_eq!(count, 1, "Should find 1 entry with `name NOT LIKE '%e'`");
105
106 let count = ConditionEntry::find_many(
107 executor,
108 expr!(ConditionEntry::name != "Alice" && ConditionEntry::name != NULL),
109 None,
110 )
111 .map_err(|e| panic!("{e:#}"))
112 .count()
113 .await;
114 assert_eq!(count, 2, "Should find 2 entries with `name != 'Alice'`");
115
116 let count = ConditionEntry::find_many(
117 executor,
118 expr!(ConditionEntry::name != ("Alice", "Bob") as IN && ConditionEntry::name != NULL),
119 None,
120 )
121 .map_err(|e| panic!("{e:#}"))
122 .count()
123 .await;
124 assert_eq!(
125 count, 1,
126 "Should find 1 entry with `name NOT IN ('Alice', 'Bob')`"
127 );
128
129 #[cfg(not(feature = "disable-glob"))]
130 {
131 let count =
132 ConditionEntry::find_many(executor, expr!(ConditionEntry::name == "A*" as GLOB), None)
133 .map_err(|e| panic!("{e:#}"))
134 .count()
135 .await;
136 assert_eq!(count, 1, "Should find 1 entry with `name GLOB 'A*'`");
137
138 let count = ConditionEntry::find_many(
139 executor,
140 expr!(ConditionEntry::name != "?li*" as GLOB),
141 None,
142 )
143 .map_err(|e| panic!("{e:#}"))
144 .count()
145 .await;
146 assert_eq!(
147 count, 2,
148 "Should find 2 entries with name not matching GLOB '?li*'"
149 );
150 }
151
152 let count = ConditionEntry::find_many(executor, expr!(!(ConditionEntry::name > "Bob")), None)
153 .map_err(|e| panic!("{e:#}"))
154 .count()
155 .await;
156 assert_eq!(count, 2, "Should find 2 entries with `NOT (name > 'Bob')`");
157
158 let count = ConditionEntry::find_many(executor, expr!(!ConditionEntry::verified), None)
159 .map_err(|e| panic!("{e:#}"))
160 .count()
161 .await;
162 assert_eq!(count, 1, "Should find 1 entry with `NOT verified`");
163}