Skip to main content

vantage_table/table/impls/
conditions.rs

1use vantage_core::{Result, error};
2use vantage_types::Entity;
3
4use crate::{conditions::ConditionHandle, table::Table, traits::table_source::TableSource};
5
6impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
7    /// Add a permanent condition to limit what records the table represents
8    pub fn add_condition(&mut self, condition: impl Into<T::Condition>) {
9        let id = -self.next_condition_id;
10        self.next_condition_id += 1;
11        self.conditions.insert(id, condition.into());
12    }
13
14    /// Add a temporary condition that can be removed later
15    pub fn temp_add_condition(&mut self, condition: impl Into<T::Condition>) -> ConditionHandle {
16        let id = self.next_condition_id;
17        self.next_condition_id += 1;
18        self.conditions.insert(id, condition.into());
19        ConditionHandle::new(id)
20    }
21
22    /// Remove a temporary condition by its handle
23    pub fn temp_remove_condition(&mut self, handle: ConditionHandle) -> Result<()> {
24        if handle.0 <= 0 {
25            return Err(error!("Cannot remove permanent condition"));
26        }
27        self.conditions.shift_remove(&handle.0);
28        Ok(())
29    }
30
31    /// Get all conditions
32    pub fn conditions(&self) -> impl Iterator<Item = &T::Condition> {
33        self.conditions.values()
34    }
35
36    /// Add a condition using the builder pattern
37    pub fn with_condition(mut self, condition: impl Into<T::Condition>) -> Self {
38        self.add_condition(condition);
39        self
40    }
41
42    /// Add a search condition that matches `value` across all columns.
43    pub fn add_search(&mut self, value: &str)
44    where
45        T: Sized,
46    {
47        let condition = self.data_source().search_table_condition(self, value);
48        self.add_condition(condition);
49    }
50
51    /// Add a search condition using the builder pattern.
52    pub fn with_search(mut self, value: &str) -> Self
53    where
54        T: Sized,
55    {
56        self.add_search(value);
57        self
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use crate::mocks::mock_table_source::MockTableSource;
64
65    use super::*;
66    use vantage_expressions::expr_any;
67    use vantage_types::EmptyEntity;
68
69    #[test]
70    fn test_temp_conditions() {
71        let ds = MockTableSource::new();
72        let mut table = Table::<_, EmptyEntity>::new("test", ds);
73
74        // Add permanent condition
75        table.add_condition(expr_any!("perm1"));
76        assert_eq!(table.conditions().count(), 1);
77
78        // Add temp conditions
79        let handle1 = table.temp_add_condition(expr_any!("temp1"));
80        let handle2 = table.temp_add_condition(expr_any!("temp2"));
81        assert_eq!(table.conditions().count(), 3);
82
83        // Remove one temp condition
84        table.temp_remove_condition(handle1).unwrap();
85        assert_eq!(table.conditions().count(), 2);
86
87        // Add another permanent
88        table.add_condition(expr_any!("perm2"));
89        assert_eq!(table.conditions().count(), 3);
90
91        // Remove second temp
92        table.temp_remove_condition(handle2).unwrap();
93        assert_eq!(table.conditions().count(), 2);
94
95        // Verify we have exactly 2 conditions left (both permanent)
96        assert_eq!(table.conditions().count(), 2);
97    }
98
99    #[test]
100    fn test_cannot_remove_permanent_condition() {
101        let ds = MockTableSource::new();
102        let mut table = Table::<_, EmptyEntity>::new("test", ds);
103
104        table.add_condition(expr_any!("perm"));
105        let _handle = table.temp_add_condition(expr_any!("temp"));
106
107        // Try to forge a handle to permanent condition (negative ID)
108        let fake_handle = ConditionHandle::new(-1);
109        let result = table.temp_remove_condition(fake_handle);
110        assert!(result.is_err());
111    }
112}