paginator_utils/
filter.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
4#[serde(rename_all = "lowercase")]
5pub enum FilterOperator {
6    Eq,
7    Ne,
8    Gt,
9    Lt,
10    Gte,
11    Lte,
12    Like,
13    ILike,
14    In,
15    NotIn,
16    IsNull,
17    IsNotNull,
18    Between,
19    Contains,
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
23#[serde(untagged)]
24pub enum FilterValue {
25    String(String),
26    Int(i64),
27    Float(f64),
28    Bool(bool),
29    Array(Vec<FilterValue>),
30    Null,
31}
32
33impl FilterValue {
34    pub fn to_sql_string(&self) -> String {
35        match self {
36            FilterValue::String(s) => format!("'{}'", s.replace('\'', "''")),
37            FilterValue::Int(i) => i.to_string(),
38            FilterValue::Float(f) => f.to_string(),
39            FilterValue::Bool(b) => if *b { "TRUE" } else { "FALSE" }.to_string(),
40            FilterValue::Array(arr) => {
41                let items: Vec<String> = arr.iter().map(|v| v.to_sql_string()).collect();
42                format!("({})", items.join(", "))
43            }
44            FilterValue::Null => "NULL".to_string(),
45        }
46    }
47}
48
49#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
50pub struct Filter {
51    pub field: String,
52    pub operator: FilterOperator,
53    pub value: FilterValue,
54}
55
56impl Filter {
57    pub fn new(field: impl Into<String>, operator: FilterOperator, value: FilterValue) -> Self {
58        Self {
59            field: field.into(),
60            operator,
61            value,
62        }
63    }
64
65    pub fn to_sql_where(&self) -> String {
66        match &self.operator {
67            FilterOperator::Eq => format!("{} = {}", self.field, self.value.to_sql_string()),
68            FilterOperator::Ne => format!("{} != {}", self.field, self.value.to_sql_string()),
69            FilterOperator::Gt => format!("{} > {}", self.field, self.value.to_sql_string()),
70            FilterOperator::Lt => format!("{} < {}", self.field, self.value.to_sql_string()),
71            FilterOperator::Gte => format!("{} >= {}", self.field, self.value.to_sql_string()),
72            FilterOperator::Lte => format!("{} <= {}", self.field, self.value.to_sql_string()),
73            FilterOperator::Like => format!("{} LIKE {}", self.field, self.value.to_sql_string()),
74            FilterOperator::ILike => format!("{} ILIKE {}", self.field, self.value.to_sql_string()),
75            FilterOperator::In => format!("{} IN {}", self.field, self.value.to_sql_string()),
76            FilterOperator::NotIn => {
77                format!("{} NOT IN {}", self.field, self.value.to_sql_string())
78            }
79            FilterOperator::IsNull => format!("{} IS NULL", self.field),
80            FilterOperator::IsNotNull => format!("{} IS NOT NULL", self.field),
81            FilterOperator::Between => {
82                if let FilterValue::Array(arr) = &self.value {
83                    if arr.len() == 2 {
84                        return format!(
85                            "{} BETWEEN {} AND {}",
86                            self.field,
87                            arr[0].to_sql_string(),
88                            arr[1].to_sql_string()
89                        );
90                    }
91                }
92                format!("{} = {}", self.field, self.value.to_sql_string())
93            }
94            FilterOperator::Contains => {
95                format!("{} @> {}", self.field, self.value.to_sql_string())
96            }
97        }
98    }
99
100    pub fn to_surrealql_where(&self) -> String {
101        match &self.operator {
102            FilterOperator::Eq => format!("{} = {}", self.field, self.value.to_sql_string()),
103            FilterOperator::Ne => format!("{} != {}", self.field, self.value.to_sql_string()),
104            FilterOperator::Gt => format!("{} > {}", self.field, self.value.to_sql_string()),
105            FilterOperator::Lt => format!("{} < {}", self.field, self.value.to_sql_string()),
106            FilterOperator::Gte => format!("{} >= {}", self.field, self.value.to_sql_string()),
107            FilterOperator::Lte => format!("{} <= {}", self.field, self.value.to_sql_string()),
108            FilterOperator::Like | FilterOperator::ILike => {
109                format!("{} ~ {}", self.field, self.value.to_sql_string())
110            }
111            FilterOperator::In => format!("{} INSIDE {}", self.field, self.value.to_sql_string()),
112            FilterOperator::NotIn => {
113                format!("{} NOT INSIDE {}", self.field, self.value.to_sql_string())
114            }
115            FilterOperator::IsNull => format!("{} IS NULL", self.field),
116            FilterOperator::IsNotNull => format!("{} IS NOT NULL", self.field),
117            FilterOperator::Between => {
118                if let FilterValue::Array(arr) = &self.value {
119                    if arr.len() == 2 {
120                        return format!(
121                            "{} >= {} AND {} <= {}",
122                            self.field,
123                            arr[0].to_sql_string(),
124                            self.field,
125                            arr[1].to_sql_string()
126                        );
127                    }
128                }
129                format!("{} = {}", self.field, self.value.to_sql_string())
130            }
131            FilterOperator::Contains => {
132                format!("{} CONTAINS {}", self.field, self.value.to_sql_string())
133            }
134        }
135    }
136}