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*/