lumus_sql_builder/sqlite/
select.rs1use super::BuildableStatement;
2use crate::errors::SqlBuilderError;
3
4#[derive(Debug)]
6pub struct Select {
7 table: String,
8 distinct: bool,
9 condition: Option<String>,
10 columns: Option<String>,
11 group: Option<String>,
12 order: Option<String>,
13 limit: Option<u32>,
14 offset: Option<u32>,
15 join: Option<Vec<String>>,
16}
17
18impl Select {
19 pub fn new(table: &str) -> Self {
27 Self {
28 table: table.to_string(),
29 distinct: false,
30 columns: None,
31 condition: None,
32 group: None,
33 order: None,
34 limit: None,
35 offset: None,
36 join: None,
37 }
38 }
39
40 pub fn from(query: &str) -> Result<Select, SqlBuilderError> {
49 let mut parts = query.split_whitespace();
50 let select = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
51 if select.to_uppercase() != "SELECT" {
52 return Err(SqlBuilderError::InvalidQuery);
53 }
54
55 let _ = parts.next().ok_or(SqlBuilderError::InvalidQuery)?; let from = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
58 if from.to_uppercase() != "FROM" {
59 return Err(SqlBuilderError::InvalidQuery);
60 }
61
62 let table = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
63
64 let mut select_builder = Select::new(table);
65
66 while let Some(part) = parts.next() {
67 match part.to_uppercase().as_str() {
68 "WHERE" => {
69 let condition = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
70 select_builder.condition(condition.to_string());
71 }
72 "GROUP" => {
73 let by = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
74 if by.to_uppercase() != "BY" {
75 return Err(SqlBuilderError::InvalidQuery);
76 }
77 let group = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
78 select_builder.group(group);
79 }
80 "ORDER" => {
81 let by = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
82 if by.to_uppercase() != "BY" {
83 return Err(SqlBuilderError::InvalidQuery);
84 }
85 let order = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
86 select_builder.order(order);
87 }
88 "LIMIT" => {
89 let limit = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
90 let limit = limit
91 .parse::<u32>()
92 .map_err(|_| SqlBuilderError::InvalidQuery)?;
93 select_builder.limit(limit);
94 }
95 "OFFSET" => {
96 let offset = parts.next().ok_or(SqlBuilderError::InvalidQuery)?;
97 let offset = offset
98 .parse::<u32>()
99 .map_err(|_| SqlBuilderError::InvalidQuery)?;
100 select_builder.offset(offset);
101 }
102 _ => return Err(SqlBuilderError::InvalidQuery),
103 }
104 }
105
106 Ok(select_builder)
107 }
108
109 pub fn distinct(&mut self) -> &mut Self {
111 self.distinct = true;
112 self
113 }
114
115 pub fn columns(&mut self, columns: &str) -> &mut Self {
117 self.columns = Some(columns.to_string());
118 self
119 }
120
121 pub fn group(&mut self, group: &str) -> &mut Self {
123 self.group = Some(group.to_string());
124 self
125 }
126
127 pub fn order(&mut self, order: &str) -> &mut Self {
129 self.order = Some(order.to_string());
130 self
131 }
132
133 pub fn condition(&mut self, condition: String) -> &mut Self {
135 self.condition = Some(condition);
136 self
137 }
138
139 pub fn limit(&mut self, limit: u32) -> &mut Self {
141 self.limit = Some(limit);
142 self
143 }
144
145 pub fn offset(&mut self, offset: u32) -> &mut Self {
147 self.offset = Some(offset);
148 self
149 }
150
151 pub fn join(&mut self, join: String) -> &mut Self {
153 match &mut self.join {
154 None => self.join = Some(vec![join]),
155 Some(j) => j.push(join),
156 }
157
158 self
159 }
160
161 pub fn build(&self) -> Result<String, SqlBuilderError> {
163 if self.table.is_empty() {
164 return Err(SqlBuilderError::EmptyTableName);
165 }
166
167 let mut statement = String::from("SELECT");
168
169 if self.distinct {
170 statement.push_str(" DISTINCT");
171 }
172
173 if let Some(columns) = &self.columns {
174 statement.push_str(&format!(" {}", columns));
175 } else {
176 statement.push_str(" *");
177 }
178
179 statement.push_str(&format!(" FROM {}", self.table));
180
181 if let Some(join) = &self.join {
182 for j in join {
183 statement.push_str(&format!(" {}", j))
184 }
185 }
186
187 if let Some(condition) = &self.condition {
188 statement.push_str(&format!(" WHERE {}", condition));
189 }
190
191 if let Some(group) = &self.group {
192 statement.push_str(&format!(" GROUP BY {}", group));
193 }
194
195 if let Some(order) = &self.order {
196 statement.push_str(&format!(" ORDER BY {}", order));
197 }
198
199 if let Some(limit) = &self.limit {
200 statement.push_str(&format!(" LIMIT {}", limit));
201 }
202
203 if let Some(offset) = &self.offset {
204 statement.push_str(&format!(" OFFSET {}", offset));
205 }
206
207 statement.push(';');
208 Ok(statement)
209 }
210}
211
212impl BuildableStatement for Select {
214 fn build(&self) -> String {
215 self.build().unwrap()
216 }
217}