Skip to main content

toasty_driver_integration_suite/tests/
embed_variant_predicate_scope.rs

1//! Boolean scope of the variant checks a predicate over an enum variant's
2//! field requires: the check is part of the predicate, so negating or
3//! combining the predicate treats the guarded comparison as a whole.
4
5use crate::prelude::*;
6use toasty::stmt::IntoExpr;
7
8#[driver_test(requires(scan))]
9pub async fn optional_field_negation(t: &mut Test) -> Result<()> {
10    #[derive(Debug, toasty::Embed)]
11    enum State {
12        Selected {
13            #[shared(value)]
14            value: Option<String>,
15        },
16        Other {
17            #[shared(value)]
18            value: Option<String>,
19        },
20    }
21
22    #[derive(Debug, toasty::Model)]
23    struct Item {
24        #[key]
25        #[auto]
26        id: uuid::Uuid,
27        state: State,
28    }
29
30    let mut db = t.setup_db(models!(Item)).await;
31    for value in [None, Some("value".to_string())] {
32        toasty::create!(Item {
33            state: State::Selected {
34                value: value.clone()
35            }
36        })
37        .exec(&mut db)
38        .await?;
39        toasty::create!(Item {
40            state: State::Other { value }
41        })
42        .exec(&mut db)
43        .await?;
44    }
45
46    // Four rows: Selected/Other with and without a value. A predicate on
47    // `selected().value()` requires the Selected variant; its negation
48    // matches every other row, including the Other rows sharing the column.
49    let value = || Item::fields().state().selected().value();
50    for (predicate, expected) in [
51        (value().is_none(), 1),
52        (value().is_some(), 1),
53        (value().is_none().not(), 3),
54        (value().is_some().not(), 3),
55        (value().into_expr().is_none().not(), 3),
56        (value().into_expr().is_some(), 1),
57        (value().is_none().eq(false), 3),
58        (value().is_none().or(value().is_some()), 2),
59        (value().is_none().or(value().is_some()).not(), 2),
60    ] {
61        assert_eq!(Item::filter(predicate).exec(&mut db).await?.len(), expected);
62    }
63    Ok(())
64}
65
66#[driver_test(requires(scan))]
67pub async fn variant_guard_through_relation(t: &mut Test) -> Result<()> {
68    #[derive(Debug, toasty::Embed)]
69    enum State {
70        Selected {
71            #[shared(value)]
72            value: String,
73        },
74        Other {
75            #[shared(value)]
76            value: String,
77        },
78    }
79
80    #[derive(Debug, toasty::Model)]
81    struct Item {
82        #[key]
83        #[auto]
84        id: uuid::Uuid,
85        state: State,
86    }
87
88    #[derive(Debug, toasty::Model)]
89    struct Link {
90        #[key]
91        #[auto]
92        id: uuid::Uuid,
93        #[index]
94        item_id: uuid::Uuid,
95        #[belongs_to(key = item_id)]
96        item: toasty::Deferred<Item>,
97    }
98
99    let mut db = t.setup_db(models!(Item, Link)).await;
100    for state in [
101        State::Selected {
102            value: "same".into(),
103        },
104        State::Other {
105            value: "same".into(),
106        },
107    ] {
108        let item = toasty::create!(Item { state }).exec(&mut db).await?;
109        toasty::create!(Link { item: &item }).exec(&mut db).await?;
110    }
111
112    // The variant check travels through the relation with the predicate:
113    // only the link whose item is Selected matches, although both items
114    // hold the same value in the shared column.
115    let state = || Link::fields().item().state();
116    for predicate in [
117        state().selected().value().eq("same"),
118        state().is_selected(),
119        state().selected().matches(|_| true.into_expr()),
120    ] {
121        assert_eq!(Link::filter(predicate).exec(&mut db).await?.len(), 1);
122    }
123    Ok(())
124}