1use keelson_core::clause::{
2 Combines, GroupBy, HasCombines, HasGroupBy, HasHaving, HasJoins, HasLimit, HasLocks, HasOffset,
3 HasOrderBy, HasSelectList, HasTableRef, HasWhere, HasWindows, HasWith, Having, Join, Limit,
4 Locks, Offset, OrderBy, SelectList, TableRef, Where, Windows, With,
5};
6use keelson_core::expr::{Expr, IntoExpr, IntoExprList};
7use keelson_core::{Dialect, Expression, Mod, Query, QueryExtensions, QueryType, SqlWriter};
8
9use super::{HasExtraTables, write_hints_and_modifiers, write_table_list};
10use crate::Mysql;
11use crate::extras::{HasHints, HasModifiers, Hints, Modifiers};
12
13#[derive(Debug, Clone, Default)]
48pub struct SelectQuery {
49 pub with: With,
51 pub hints: Hints,
53 pub modifiers: Modifiers,
55 pub select_list: SelectList,
57 pub from: TableRef,
59 pub extra_from: Vec<TableRef>,
61 pub where_: Where,
63 pub group_by: GroupBy,
65 pub having: Having,
67 pub windows: Windows,
69 pub order_by: OrderBy,
71 pub limit: Limit,
73 pub offset: Offset,
75 pub locks: Locks,
77 pub lock_in_share_mode: bool,
79 pub combines: Combines,
81}
82
83impl SelectQuery {
84 pub fn new() -> SelectQuery {
86 SelectQuery::default()
87 }
88
89 pub fn apply(&mut self, mods: impl Mod<SelectQuery>) {
91 mods.apply(self);
92 }
93
94 fn has_tail_clauses(&self) -> bool {
97 !self.order_by.is_empty()
98 || !self.limit.is_empty()
99 || !self.offset.is_empty()
100 || !self.locks.is_empty()
101 || self.lock_in_share_mode
102 }
103}
104
105impl Expression for SelectQuery {
106 fn write_sql(&self, w: &mut SqlWriter<'_>) {
107 w.write_if(!self.with.is_empty(), "", &self.with, " ");
108
109 let parens = self
110 .combines
111 .parenthesises_leading_query(self.has_tail_clauses());
112 if parens {
113 w.push_str("(");
114 }
115
116 w.push_str("SELECT ");
117 write_hints_and_modifiers(w, &self.hints, &self.modifiers);
118 w.write_expr(&self.select_list);
120
121 write_table_list(
122 w,
123 " FROM ",
124 &self.from,
125 &self.extra_from,
126 "the FROM item its joins attach to",
127 );
128
129 w.write_if(!self.where_.is_empty(), " ", &self.where_, "");
130 w.write_if(!self.group_by.is_empty(), " ", &self.group_by, "");
131 w.write_if(!self.having.is_empty(), " ", &self.having, "");
132 w.write_if(!self.windows.is_empty(), " ", &self.windows, "");
133 w.write_if(!self.order_by.is_empty(), " ", &self.order_by, "");
134 w.write_if(!self.limit.is_empty(), " ", &self.limit, "");
135 w.write_if(!self.offset.is_empty(), " ", &self.offset, "");
136 w.write_if(!self.locks.is_empty(), " ", &self.locks, "");
137 if self.lock_in_share_mode {
138 w.push_str(" LOCK IN SHARE MODE");
139 }
140
141 if parens {
142 w.push_str(")");
143 }
144
145 w.write_if(!self.combines.is_empty(), " ", &self.combines, "");
146 }
147}
148
149impl Query for SelectQuery {
150 fn query_type(&self) -> QueryType {
151 QueryType::Select
152 }
153
154 fn dialect(&self) -> &dyn Dialect {
155 &Mysql
156 }
157}
158
159impl<H, L, M> QueryExtensions<H, L, M> for SelectQuery {}
160
161impl IntoExpr for SelectQuery {
162 fn into_expr(self) -> Expr {
163 crate::query(self)
164 }
165}
166
167impl IntoExprList for SelectQuery {
168 fn into_expr_list(self) -> Vec<Expr> {
169 vec![self.into_expr()]
170 }
171}
172
173impl HasWith for SelectQuery {
174 fn with_mut(&mut self) -> &mut With {
175 &mut self.with
176 }
177}
178
179impl HasHints for SelectQuery {
180 fn hints_mut(&mut self) -> &mut Hints {
181 &mut self.hints
182 }
183}
184
185impl HasModifiers for SelectQuery {
186 fn modifiers_mut(&mut self) -> &mut Modifiers {
187 &mut self.modifiers
188 }
189}
190
191impl HasSelectList for SelectQuery {
192 fn select_list_mut(&mut self) -> &mut SelectList {
193 &mut self.select_list
194 }
195}
196
197impl HasTableRef for SelectQuery {
198 fn table_ref_mut(&mut self) -> &mut TableRef {
199 &mut self.from
200 }
201}
202
203impl HasExtraTables for SelectQuery {
204 fn extra_tables_mut(&mut self) -> &mut Vec<TableRef> {
205 &mut self.extra_from
206 }
207}
208
209impl HasJoins for SelectQuery {
210 fn joins_mut(&mut self) -> &mut Vec<Join> {
211 &mut self.from.joins
212 }
213}
214
215impl HasWhere for SelectQuery {
216 fn where_mut(&mut self) -> &mut Where {
217 &mut self.where_
218 }
219}
220
221impl HasGroupBy for SelectQuery {
222 fn group_by_mut(&mut self) -> &mut GroupBy {
223 &mut self.group_by
224 }
225}
226
227impl HasHaving for SelectQuery {
228 fn having_mut(&mut self) -> &mut Having {
229 &mut self.having
230 }
231}
232
233impl HasWindows for SelectQuery {
234 fn windows_mut(&mut self) -> &mut Windows {
235 &mut self.windows
236 }
237}
238
239impl HasOrderBy for SelectQuery {
240 fn order_by_mut(&mut self) -> &mut OrderBy {
241 &mut self.order_by
242 }
243}
244
245impl HasLimit for SelectQuery {
246 fn limit_mut(&mut self) -> &mut Limit {
247 &mut self.limit
248 }
249}
250
251impl HasOffset for SelectQuery {
252 fn offset_mut(&mut self) -> &mut Offset {
253 &mut self.offset
254 }
255}
256
257impl HasLocks for SelectQuery {
258 fn locks_mut(&mut self) -> &mut Locks {
259 &mut self.locks
260 }
261}
262
263impl HasCombines for SelectQuery {
264 fn combines_mut(&mut self) -> &mut Combines {
265 &mut self.combines
266 }
267}