derive_sql/selectable/filter/generic.rs
1//! Implement a generic filter operator to support filter such as `name="John"` as a combination of `(key, operator, value)`
2//! Supported operators are `=`, `<`, `<=`, `>`, `>=`
3use super::*;
4use value::Value;
5
6pub enum Operator {
7 Equal,
8 Lower,
9 LowerEqual,
10 Greater,
11 GreaterEqual,
12}
13
14impl std::fmt::Display for Operator {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 Operator::Equal => write!(f, "="),
18 Operator::Lower => write!(f, "<"),
19 Operator::LowerEqual => write!(f, "<="),
20 Operator::Greater => write!(f, ">"),
21 Operator::GreaterEqual => write!(f, ">="),
22 }
23 }
24}
25
26pub struct Filter<T>
27where T: std::fmt::Display
28{
29 key: String,
30 value: Value<T>,
31 operator: Operator,
32}
33
34impl<T> std::convert::From<(String, Operator, Value<T>)> for Filter<T>
35where T: std::fmt::Display
36{
37 fn from((key, operator, value): (String, Operator, Value<T>)) -> Self {
38 Filter { key, value, operator }
39 }
40}
41
42impl<T> std::convert::From<(&str, Operator, Value<T>)> for Filter<T>
43where T: std::fmt::Display
44{
45 fn from((key, operator, value): (&str, Operator, Value<T>)) -> Self {
46 Filter { key: key.to_string(), value, operator }
47 }
48}
49
50impl<T> FilterTrait for Filter<T>
51where T: std::fmt::Display
52{
53 fn filter(&self) -> String {
54 format!("`{0}` {1} {2}", self.key, self.operator, self.value)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn it_outputs_correct_statement() -> std::result::Result<(), Box<dyn std::error::Error>> {
64 let g: Filter<u32> = ("user_id", Operator::Equal, 1.into()).into();
65 assert!(FilterTrait::filter(&g).eq("`user_id` = 1"));
66 Ok(())
67 }
68}
69
70/*
71pub struct Generic<T>
72where T: std::fmt::Display
73{
74 filter: Option<Filter<T>>,
75}
76
77impl<T> std::convert::From<()> for Generic<T>
78where T: std::fmt::Display
79{
80 fn from(_: ()) -> Self {
81 Generic { filter: None, next: None }
82 }
83}
84
85impl<T> std::convert::From<(String, Operator, Value<T>)> for Generic<T>
86where T: std::fmt::Display
87{
88 fn from((key, operator, value): (String, Operator, Value<T>)) -> Self {
89 Generic { filter: Some(Filter { key, value, operator }), next: None }
90 }
91}
92
93impl<T> std::convert::From<(&str, Operator, Value<T>)> for Generic<T>
94where T: std::fmt::Display
95{
96 fn from((key, operator, value): (&str, Operator, Value<T>)) -> Self {
97 Generic { filter: Some(Filter { key: key.to_string(), value, operator }), next: None }
98 }
99}
100
101impl<T> Filterable for Generic<T>
102where T: std::fmt::Display
103{
104 fn filter(&self) -> Option<String> {
105 self.filter
106 .as_ref()
107 .map(|v| format!("`{0}` {1} {2}", v.key, v.operator, v.value))
108 }
109
110 fn next(&self) -> &Option<Box<dyn Selectable>> { &self.next }
111 fn and(mut self, next: Box<dyn Selectable>) -> Self { self.next = Some(next); self }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn it_outputs_correct_statement() -> std::result::Result<(), Box<dyn std::error::Error>> {
120 let g: Generic<u32> = ("user_id", Operator::Equal, 1.into()).into();
121 assert!(filter::Filterable::filter(&g).unwrap().eq("`user_id` = 1"));
122 assert!(g.next().is_none());
123
124 Ok(())
125 }
126}
127*/