derive_sql/structs/
field.rs

1use super::*;
2
3/// Struct to facilitate the definiion of a condition associated with a given field
4/// For example, create a condition to filter name column equal to 'Jane':
5///
6/// ```rust
7/// # #[cfg(feature = "sqlite")]
8/// # fn wrapper() {
9/// let conn = rusqlite::Connection::open_in_memory().unwrap();
10/// use derive_sql::structs::{Field, filter, order};
11/// use derive_sql::traits::{FlavoredFilter, FlavoredOrder};
12///
13/// let condition: filter::Condition<_> = Field::from("name").eq("Jane");
14/// assert!(condition.filter(&conn).unwrap().eq("`name` = 'Jane'"));
15///
16/// let condition: order::Condition = Field::from("name").ascending();
17/// assert!(condition.as_order_clause(&conn).unwrap().eq("`name` ASC"));
18///
19/// let condition: filter::Condition<_> = Field::from_table_column("table", "col").eq("val");
20/// assert!(condition.filter(&conn).unwrap().eq("`table`.`col` = 'val'"));
21/// # }()
22/// ```
23pub struct Field {
24  table: Option<String>,
25  label: String,
26}
27
28impl Field {
29  /// Create a new field with the given label
30  pub fn from(label: &str) -> Field {
31    Field { table: None, label: label.to_string() }
32  }
33
34  /// Create a new field with the given label
35  pub fn from_table_column(table: &str, label: &str) -> Field {
36    Field { table: Some(table.to_string()), label: label.to_string() }
37  }
38
39  /// Generate a test on Null
40  pub fn is_none(self) -> filter::Condition<bool> {
41    filter::Condition::from_table_label_operator(
42      self.table,
43      self.label,
44      filter::Operator::IsNull,
45    )
46  }
47
48  /// Generate a test on Not Null
49  pub fn is_some(self) -> filter::Condition<bool> {
50    filter::Condition::from_table_label_operator(
51      self.table,
52      self.label,
53      filter::Operator::IsNotNull,
54    )
55  }
56
57  /// Generate an 'equal' condition
58  pub fn eq<T>(self, t: T) -> filter::Condition<T> 
59  where filter::Value<T>: std::convert::From<T>,
60        T: std::fmt::Display,
61  {
62    filter::Condition::from_table_label_operator(
63      self.table,
64      self.label,
65      filter::Operator::Equal(t.into()),
66    )
67  }
68
69  /// Generate a 'not-equal' condition
70  pub fn ne<T>(self, t: T) -> filter::Condition<T> 
71  where filter::Value<T>: std::convert::From<T>,
72        T: std::fmt::Display,
73  {
74    filter::Condition::from_table_label_operator(
75      self.table,
76      self.label,
77      filter::Operator::NotEqual(t.into()),
78    )
79  }
80
81  /// Generate a 'greater than' condition
82  pub fn gt<T>(self, t: T) -> filter::Condition<T>
83  where filter::Value<T>: std::convert::From<T>,
84        T: std::fmt::Display
85  {
86    filter::Condition::from_table_label_operator(
87      self.table,
88      self.label,
89      filter::Operator::GreaterThan(t.into()),
90    )
91  }
92
93  /// Generate a 'greater equal' condition
94  pub fn ge<T>(self, t: T) -> filter::Condition<T>
95  where filter::Value<T>: std::convert::From<T>,
96        T: std::fmt::Display
97  {
98    filter::Condition::from_table_label_operator(
99      self.table,
100      self.label,
101      filter::Operator::GreaterEqual(t.into()),
102    )
103  }
104
105  /// Generate a 'lower than' condition
106  pub fn lt<T>(self, t: T) -> filter::Condition<T>
107  where filter::Value<T>: std::convert::From<T>,
108        T: std::fmt::Display
109  {
110    filter::Condition::from_table_label_operator(
111      self.table,
112      self.label,
113      filter::Operator::LowerThan(t.into()),
114    )
115  }
116
117  /// Generate a 'lower equal' condition
118  pub fn le<T>(self, t: T) -> filter::Condition<T>
119  where filter::Value<T>: std::convert::From<T>,
120        T: std::fmt::Display
121  {
122    filter::Condition::from_table_label_operator(
123      self.table,
124      self.label,
125      filter::Operator::LowerEqual(t.into()),
126    )
127  }
128
129  /// Generate an ascending order clause condition
130  pub fn ascending(self) -> order::Condition
131  {
132    order::Condition::from_table_label_operator(
133      self.table,
134      self.label,
135      order::Operator::Ascending,
136    )
137  }
138
139  /// Generate a descending order clause condition
140  pub fn descending(self) -> order::Condition
141  {
142    order::Condition::from_table_label_operator(
143      self.table,
144      self.label,
145      order::Operator::Descending,
146    )
147  }
148}
149
150#[cfg(test)]
151mod tests {
152  use super::*;
153
154  type Row = traits::tests::Row;
155
156  #[test]
157  fn it_display_correct_clause_for_null_not_null_tests() -> Result<()> {
158    use traits::FlavoredFilter;
159    let conn = traits::tests::SQLiteFlavoredConnection {};
160    assert!(Field::from("key").is_some().filter::<_, Row>(&conn)?.eq("`key` IS NOT NULL"));
161    assert!(Field::from("key").is_none().filter::<_, Row>(&conn)?.eq("`key` IS NULL"));
162    Ok(())
163  }
164
165  #[test]
166  fn it_display_correct_clause_for_u32() -> Result<()> {
167    use traits::FlavoredFilter;
168    let conn = traits::tests::SQLiteFlavoredConnection {};
169
170    assert!(Field::from("key").eq(1u32).filter::<_, Row>(&conn)?.eq("`key` = 1"));
171    assert!(Field::from("key").ne(1u32).filter::<_, Row>(&conn)?.eq("`key` != 1"));
172    assert!(Field::from("key").gt(2u32).filter::<_, Row>(&conn)?.eq("`key` > 2"));
173    assert!(Field::from("key").ge(2u32).filter::<_, Row>(&conn)?.eq("`key` >= 2"));
174    assert!(Field::from("key").lt(2u32).filter::<_, Row>(&conn)?.eq("`key` < 2"));
175    assert!(Field::from("key").le(2u32).filter::<_, Row>(&conn)?.eq("`key` <= 2"));
176
177    Ok(())
178  }
179
180  #[test]
181  fn it_display_correct_clause_for_string() -> Result<()> {
182    use traits::FlavoredFilter;
183    let conn = traits::tests::SQLiteFlavoredConnection {};
184
185    assert!(Field::from("key_str").eq("val").filter::<_, Row>(&conn)?.eq("`key_str` = 'val'"));
186    assert!(Field::from("key_str").ne("val").filter::<_, Row>(&conn)?.eq("`key_str` != 'val'"));
187    assert!(Field::from("key_str").gt("val").filter::<_, Row>(&conn)?.eq("`key_str` > 'val'"));
188    assert!(Field::from("key_str").ge("val").filter::<_, Row>(&conn)?.eq("`key_str` >= 'val'"));
189    assert!(Field::from("key_str").lt("val").filter::<_, Row>(&conn)?.eq("`key_str` < 'val'"));
190    assert!(Field::from("key_str").le("val").filter::<_, Row>(&conn)?.eq("`key_str` <= 'val'"));
191
192    Ok(())
193  }
194
195  #[test]
196  fn it_display_correct_order_clause() -> Result<()> {
197    use traits::FlavoredOrder;
198    let conn = traits::tests::SQLiteFlavoredConnection {};
199
200    assert!(Field::from("order").ascending().as_order_clause::<_, Row>(&conn)?.eq("`order` ASC"));
201    assert!(Field::from("order").descending().as_order_clause::<_, Row>(&conn)?.eq("`order` DESC"));
202
203    Ok(())
204  }
205}