pgsql_builder/
select.rs

1use modifier::{Modifier, Set};
2use std::borrow::Cow;
3use super::{
4    util, Condition, Conditions, Limit, Offset, Order, Orders, Query, Selection, Selections,
5    Statement
6};
7
8pub struct Select<'a> {
9    table: Cow<'static, str>,
10    conditions: Conditions<'a>,
11    selections: Selections,
12    orders: Orders,
13    limit: Option<Limit>,
14    offset: Option<Offset>,
15}
16
17impl<'a> Select<'a> {
18    pub fn new(table: Cow<'static, str>) -> Select<'a> {
19        Select {
20            table: table,
21            conditions: vec![],
22            selections: vec![],
23            orders: vec![],
24            limit: None,
25            offset: None
26        }
27    }
28}
29
30impl<'a> Statement<'a> for Select<'a> {
31    fn into_query(self) -> Query<'a> {
32        let mut query = String::from("SELECT ");
33
34        if !self.selections.is_empty() {
35            query.push_str(&util::keyword_list(self.selections.iter().map(|a| &a.0)));
36        } else {
37            query.push('*');
38        }
39
40        query.push_str(&format!(" FROM {}", self.table));
41
42        if !self.conditions.is_empty() {
43            query.push_str(" WHERE ");
44            query.push_str(&util::condition_list(&self.conditions, 1));
45        }
46
47        if !self.orders.is_empty() {
48            query.push_str(" ORDER BY ");
49            query.push_str(&util::order_list(&self.orders));
50        }
51
52        if let Some(limit) = self.limit {
53            query.push_str(&format!(" LIMIT {}", limit));
54        }
55
56        if let Some(offset) = self.offset {
57            query.push_str(&format!(" OFFSET {}", offset));
58        }
59
60        query.push(';');
61
62        let condition_predicates = self.conditions.into_iter().map(|a| a.1);
63        let condition_values = condition_predicates.flat_map(|p| p.into_values_iter());
64        let values = condition_values.collect::<Vec<_>>();
65
66        Query(query, values)
67    }
68}
69
70impl<'a> Set for Select<'a> { }
71
72impl<'a> Modifier<Select<'a>> for Condition<'a> {
73    fn modify(self, select: &mut Select<'a>) {
74        select.conditions.push(self);
75    }
76}
77
78impl<'a> Modifier<Select<'a>> for Conditions<'a> {
79    fn modify(mut self, select: &mut Select<'a>) {
80        select.conditions.append(&mut self);
81    }
82}
83
84impl<'a> Modifier<Select<'a>> for Selection {
85    fn modify(self, select: &mut Select<'a>) {
86        select.selections.push(self);
87    }
88}
89
90impl<'a> Modifier<Select<'a>> for Selections {
91    fn modify(mut self, select: &mut Select<'a>) {
92        select.selections.append(&mut self);
93    }
94}
95
96impl<'a> Modifier<Select<'a>> for Order {
97    fn modify(self, select: &mut Select<'a>) {
98        select.orders.push(self);
99    }
100}
101
102impl<'a> Modifier<Select<'a>> for Orders {
103    fn modify(mut self, select: &mut Select<'a>) {
104        select.orders.append(&mut self);
105    }
106}
107
108impl<'a> Modifier<Select<'a>> for Limit {
109    fn modify(self, select: &mut Select<'a>) {
110        select.limit = Some(self);
111    }
112}
113
114impl<'a> Modifier<Select<'a>> for Offset {
115    fn modify(self, select: &mut Select<'a>) {
116        select.offset = Some(self);
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use ::{Condition, Limit, Offset, Predicate, Selection, Set, Statement};
123    use super::*;
124
125    #[test]
126    fn select() {
127        let expected = "SELECT name FROM test_table WHERE id = $1 AND xyz < $2;";
128
129        let id = 1;
130
131        {
132            let select = Select::new("test_table".into())
133                .set(Selection("name".into()))
134                .set(Condition("id".into(), Predicate::Equal(&id)))
135                .set(Condition("xyz".into(), Predicate::Less(&id)));
136            assert_eq!(select.into_query().0, expected);
137        }
138    }
139
140    #[test]
141    fn select_all() {
142        let expected = "SELECT * FROM test_table WHERE id = $1 LIMIT 20 OFFSET 5;";
143
144        let id = 1;
145
146        {
147            let select = Select::new("test_table".into())
148                .set(Condition("id".into(), Predicate::Equal(&id)))
149                .set(Limit(20))
150                .set(Offset(5));
151            assert_eq!(select.into_query().0, expected);
152        }
153    }
154}