Skip to main content

postgrest_parser/ast/
filter.rs

1use super::Field;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum FilterOperator {
7    Eq,
8    Neq,
9    Gt,
10    Gte,
11    Lt,
12    Lte,
13    Like,
14    Ilike,
15    Match,
16    Imatch,
17    In,
18    Is,
19    Fts,
20    Plfts,
21    Phfts,
22    Wfts,
23    Cs,
24    Cd,
25    Ov,
26    Sl,
27    Sr,
28    Nxl,
29    Nxr,
30    Adj,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
34#[serde(rename_all = "snake_case")]
35pub enum Quantifier {
36    Any,
37    All,
38}
39
40#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum FilterValue {
43    Single(String),
44    List(Vec<String>),
45}
46
47impl FilterValue {
48    pub fn as_str(&self) -> Option<&str> {
49        match self {
50            FilterValue::Single(s) => Some(s.as_str()),
51            FilterValue::List(_) => None,
52        }
53    }
54
55    pub fn as_list(&self) -> Option<&[String]> {
56        match self {
57            FilterValue::Single(_) => None,
58            FilterValue::List(list) => Some(list.as_slice()),
59        }
60    }
61
62    pub fn to_json(&self) -> serde_json::Value {
63        match self {
64            FilterValue::Single(s) => serde_json::Value::String(s.clone()),
65            FilterValue::List(list) => serde_json::Value::Array(
66                list.iter()
67                    .map(|s| {
68                        if let Ok(i) = s.parse::<i64>() {
69                            serde_json::Value::Number(i.into())
70                        } else if let Ok(f) = s.parse::<f64>() {
71                            if let Some(num) = serde_json::Number::from_f64(f) {
72                                serde_json::Value::Number(num)
73                            } else {
74                                serde_json::Value::String(s.clone())
75                            }
76                        } else {
77                            serde_json::Value::String(s.clone())
78                        }
79                    })
80                    .collect(),
81            ),
82        }
83    }
84}
85
86impl From<&str> for FilterValue {
87    fn from(s: &str) -> Self {
88        FilterValue::Single(s.to_string())
89    }
90}
91
92impl From<String> for FilterValue {
93    fn from(s: String) -> Self {
94        FilterValue::Single(s)
95    }
96}
97
98impl From<Vec<String>> for FilterValue {
99    fn from(v: Vec<String>) -> Self {
100        FilterValue::List(v)
101    }
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
105pub struct Filter {
106    pub field: Field,
107    pub operator: FilterOperator,
108    pub value: FilterValue,
109    pub quantifier: Option<Quantifier>,
110    pub language: Option<String>,
111    pub negated: bool,
112}
113
114impl Filter {
115    pub fn new(field: Field, operator: FilterOperator, value: FilterValue) -> Self {
116        Self {
117            field,
118            operator,
119            value,
120            quantifier: None,
121            language: None,
122            negated: false,
123        }
124    }
125
126    pub fn with_quantifier(mut self, quantifier: Quantifier) -> Self {
127        self.quantifier = Some(quantifier);
128        self
129    }
130
131    pub fn with_language(mut self, language: impl Into<String>) -> Self {
132        self.language = Some(language.into());
133        self
134    }
135
136    pub fn negated(mut self) -> Self {
137        self.negated = true;
138        self
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_filter_new() {
148        let field = Field::new("id");
149        let filter = Filter::new(
150            field,
151            FilterOperator::Eq,
152            FilterValue::Single("1".to_string()),
153        );
154
155        assert_eq!(filter.operator, FilterOperator::Eq);
156        assert!(!filter.negated);
157        assert!(filter.quantifier.is_none());
158    }
159
160    #[test]
161    fn test_filter_with_quantifier() {
162        let field = Field::new("status");
163        let filter = Filter::new(
164            field,
165            FilterOperator::Eq,
166            FilterValue::List(vec!["active".to_string(), "pending".to_string()]),
167        )
168        .with_quantifier(Quantifier::Any);
169
170        assert_eq!(filter.quantifier, Some(Quantifier::Any));
171    }
172
173    #[test]
174    fn test_filter_negated() {
175        let field = Field::new("status");
176        let filter = Filter::new(
177            field,
178            FilterOperator::Eq,
179            FilterValue::Single("deleted".to_string()),
180        )
181        .negated();
182
183        assert!(filter.negated);
184    }
185
186    #[test]
187    fn test_filter_value_as_str() {
188        let value = FilterValue::Single("test".to_string());
189        assert_eq!(value.as_str(), Some("test"));
190    }
191
192    #[test]
193    fn test_filter_value_as_list() {
194        let value = FilterValue::List(vec!["a".to_string(), "b".to_string()]);
195        let expected: Vec<String> = vec!["a".to_string(), "b".to_string()];
196        assert_eq!(value.as_list(), Some(expected.as_slice()));
197    }
198
199    #[test]
200    fn test_filter_value_to_json() {
201        let value = FilterValue::Single("test".to_string());
202        let json = value.to_json();
203        assert_eq!(json, serde_json::Value::String("test".to_string()));
204    }
205
206    #[test]
207    fn test_filter_value_list_to_json() {
208        let value = FilterValue::List(vec!["1".to_string(), "2".to_string(), "3".to_string()]);
209        let json = value.to_json();
210        match json {
211            serde_json::Value::Array(arr) => {
212                assert_eq!(arr.len(), 3);
213                assert_eq!(arr[0], serde_json::Value::Number(1.into()));
214            }
215            _ => panic!("Expected array"),
216        }
217    }
218}