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}