Skip to main content

tank_tests/
conditions.rs

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    // Setup
24    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    // Operations
32    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}