keelson_sqlite/statement/
select.rs1use keelson_core::clause::{
2 GroupBy, HasGroupBy, HasHaving, HasJoins, HasLimit, HasOffset, HasOrderBy, HasSelectList,
3 HasTableRef, HasValues, HasWhere, HasWindows, HasWith, Having, Join, Limit, Offset, OrderBy,
4 SelectList, TableRef, Values, Where, Windows, With,
5};
6use keelson_core::expr::{Expr, IntoExpr, IntoExprList};
7use keelson_core::{Dialect, Error, Expression, Mod, Query, QueryExtensions, QueryType, SqlWriter};
8
9use super::{HasExtraTables, write_from_list};
10use crate::Sqlite;
11use crate::extras::{Compounds, HasCompounds};
12
13#[derive(Debug, Clone, Default)]
54pub struct SelectQuery {
55 pub with: With,
57 pub distinct: bool,
59 pub select_list: SelectList,
61 pub values: Values,
63 pub from: TableRef,
65 pub extra_from: Vec<TableRef>,
67 pub where_: Where,
69 pub group_by: GroupBy,
71 pub having: Having,
73 pub windows: Windows,
75 pub compounds: Compounds,
77 pub order_by: OrderBy,
79 pub limit: Limit,
81 pub offset: Offset,
83}
84
85impl SelectQuery {
86 pub fn new() -> SelectQuery {
88 SelectQuery::default()
89 }
90
91 pub fn apply(&mut self, mods: impl Mod<SelectQuery>) {
93 mods.apply(self);
94 }
95
96 fn select_only_clause(&self) -> Option<&'static str> {
99 if self.distinct {
100 Some("DISTINCT")
101 } else if !self.select_list.is_empty() {
102 Some("a result-column list")
103 } else if !self.from.is_empty() || !self.extra_from.is_empty() {
104 Some("a FROM clause")
105 } else if !self.where_.is_empty() {
106 Some("a WHERE clause")
107 } else if !self.group_by.is_empty() {
108 Some("a GROUP BY clause")
109 } else if !self.having.is_empty() {
110 Some("a HAVING clause")
111 } else if !self.windows.is_empty() {
112 Some("a WINDOW clause")
113 } else {
114 None
115 }
116 }
117
118 fn write_core(&self, w: &mut SqlWriter<'_>) {
120 if !self.values.is_empty() {
121 if let Some(clause) = self.select_only_clause() {
122 w.record_error(Error::other(format!(
123 "a VALUES statement cannot carry {clause}"
124 )));
125 return;
126 }
127 w.write_expr(&self.values);
128 return;
129 }
130
131 w.push_str("SELECT ");
132 if self.distinct {
133 w.push_str("DISTINCT ");
134 }
135 w.write_expr(&self.select_list);
137
138 write_from_list(
139 w,
140 " FROM ",
141 &self.from,
142 &self.extra_from,
143 "the FROM item its joins attach to",
144 );
145
146 w.write_if(!self.where_.is_empty(), " ", &self.where_, "");
147 w.write_if(!self.group_by.is_empty(), " ", &self.group_by, "");
148 w.write_if(!self.having.is_empty(), " ", &self.having, "");
149 w.write_if(!self.windows.is_empty(), " ", &self.windows, "");
150 }
151}
152
153impl Expression for SelectQuery {
154 fn write_sql(&self, w: &mut SqlWriter<'_>) {
155 w.write_if(!self.with.is_empty(), "", &self.with, " ");
156
157 self.write_core(w);
158
159 w.write_if(!self.compounds.is_empty(), " ", &self.compounds, "");
160 w.write_if(!self.order_by.is_empty(), " ", &self.order_by, "");
161
162 if self.limit.is_empty() && !self.offset.is_empty() {
163 w.record_error(Error::Incomplete("the LIMIT that an OFFSET belongs to"));
166 return;
167 }
168 w.write_if(!self.limit.is_empty(), " ", &self.limit, "");
169 w.write_if(!self.offset.is_empty(), " ", &self.offset, "");
170 }
171}
172
173impl Query for SelectQuery {
174 fn query_type(&self) -> QueryType {
175 QueryType::Select
176 }
177
178 fn dialect(&self) -> &dyn Dialect {
179 &Sqlite
180 }
181}
182
183impl<H, L, M> QueryExtensions<H, L, M> for SelectQuery {}
184
185impl IntoExpr for SelectQuery {
186 fn into_expr(self) -> Expr {
187 crate::query(self)
188 }
189}
190
191impl IntoExprList for SelectQuery {
192 fn into_expr_list(self) -> Vec<Expr> {
193 vec![self.into_expr()]
194 }
195}
196
197impl HasWith for SelectQuery {
198 fn with_mut(&mut self) -> &mut With {
199 &mut self.with
200 }
201}
202
203impl HasSelectList for SelectQuery {
204 fn select_list_mut(&mut self) -> &mut SelectList {
205 &mut self.select_list
206 }
207}
208
209impl HasValues for SelectQuery {
210 fn values_mut(&mut self) -> &mut Values {
211 &mut self.values
212 }
213}
214
215impl HasTableRef for SelectQuery {
216 fn table_ref_mut(&mut self) -> &mut TableRef {
217 &mut self.from
218 }
219}
220
221impl HasExtraTables for SelectQuery {
222 fn extra_tables_mut(&mut self) -> &mut Vec<TableRef> {
223 &mut self.extra_from
224 }
225}
226
227impl HasJoins for SelectQuery {
228 fn joins_mut(&mut self) -> &mut Vec<Join> {
229 &mut self.from.joins
230 }
231}
232
233impl HasWhere for SelectQuery {
234 fn where_mut(&mut self) -> &mut Where {
235 &mut self.where_
236 }
237}
238
239impl HasGroupBy for SelectQuery {
240 fn group_by_mut(&mut self) -> &mut GroupBy {
241 &mut self.group_by
242 }
243}
244
245impl HasHaving for SelectQuery {
246 fn having_mut(&mut self) -> &mut Having {
247 &mut self.having
248 }
249}
250
251impl HasWindows for SelectQuery {
252 fn windows_mut(&mut self) -> &mut Windows {
253 &mut self.windows
254 }
255}
256
257impl HasOrderBy for SelectQuery {
258 fn order_by_mut(&mut self) -> &mut OrderBy {
259 &mut self.order_by
260 }
261}
262
263impl HasLimit for SelectQuery {
264 fn limit_mut(&mut self) -> &mut Limit {
265 &mut self.limit
266 }
267}
268
269impl HasOffset for SelectQuery {
270 fn offset_mut(&mut self) -> &mut Offset {
271 &mut self.offset
272 }
273}
274
275impl HasCompounds for SelectQuery {
276 fn compounds_mut(&mut self) -> &mut Compounds {
277 &mut self.compounds
278 }
279}