1use crate::helpers;
2use crate::values::SQLiteValue;
3use drizzle_core::traits::{IsInSchema, SQLTable};
4use drizzle_core::{SQL, ToSQL};
5use paste::paste;
6use std::fmt::Debug;
7use std::marker::PhantomData;
8
9use super::ExecutableState;
11
12#[derive(Debug, Clone, Copy, Default)]
18pub struct SelectInitial;
19
20impl SelectInitial {
21 #[inline]
23 pub const fn new() -> Self {
24 Self
25 }
26}
27
28#[derive(Debug, Clone, Copy, Default)]
30pub struct SelectFromSet;
31
32#[derive(Debug, Clone, Copy, Default)]
34pub struct SelectJoinSet;
35
36#[derive(Debug, Clone, Copy, Default)]
38pub struct SelectWhereSet;
39
40#[derive(Debug, Clone, Copy, Default)]
42pub struct SelectGroupSet;
43
44#[derive(Debug, Clone, Copy, Default)]
46pub struct SelectOrderSet;
47
48#[derive(Debug, Clone, Copy, Default)]
50pub struct SelectLimitSet;
51
52#[derive(Debug, Clone, Copy, Default)]
54pub struct SelectOffsetSet;
55
56impl SelectFromSet {
58 #[inline]
59 pub const fn new() -> Self {
60 Self
61 }
62}
63impl SelectJoinSet {
64 #[inline]
65 pub const fn new() -> Self {
66 Self
67 }
68}
69impl SelectWhereSet {
70 #[inline]
71 pub const fn new() -> Self {
72 Self
73 }
74}
75impl SelectGroupSet {
76 #[inline]
77 pub const fn new() -> Self {
78 Self
79 }
80}
81impl SelectOrderSet {
82 #[inline]
83 pub const fn new() -> Self {
84 Self
85 }
86}
87impl SelectLimitSet {
88 #[inline]
89 pub const fn new() -> Self {
90 Self
91 }
92}
93impl SelectOffsetSet {
94 #[inline]
95 pub const fn new() -> Self {
96 Self
97 }
98}
99
100macro_rules! join_impl {
101 () => {
102 join_impl!(natural);
103 join_impl!(natural_left);
104 join_impl!(left);
105 join_impl!(left_outer);
106 join_impl!(natural_left_outer);
107 join_impl!(natural_right);
108 join_impl!(right);
109 join_impl!(right_outer);
110 join_impl!(natural_right_outer);
111 join_impl!(natural_full);
112 join_impl!(full);
113 join_impl!(full_outer);
114 join_impl!(natural_full_outer);
115 join_impl!(inner);
116 join_impl!(cross);
117 };
118 ($type:ident) => {
119 paste! {
120 pub fn [<$type _join>]<U: IsInSchema<S> + SQLTable<'a, SQLiteValue<'a>>>(
121 self,
122 table: U,
123 condition: SQL<'a, SQLiteValue<'a>>,
124 ) -> SelectBuilder<'a, S, SelectJoinSet, T> {
125 SelectBuilder {
126 sql: self.sql.append(helpers::[<$type _join>](table, condition)),
127 schema: PhantomData,
128 state: PhantomData,
129 table: PhantomData,
130 }
131 }
132 }
133 };
134}
135
136impl ExecutableState for SelectFromSet {}
138impl ExecutableState for SelectWhereSet {}
139impl ExecutableState for SelectLimitSet {}
140impl ExecutableState for SelectOffsetSet {}
141impl ExecutableState for SelectOrderSet {}
142impl ExecutableState for SelectGroupSet {}
143impl ExecutableState for SelectJoinSet {}
144
145pub type SelectBuilder<'a, Schema, State, Table = ()> =
151 super::QueryBuilder<'a, Schema, State, Table>;
152
153impl<'a, S> SelectBuilder<'a, S, SelectInitial> {
158 #[inline]
160 pub fn from<T>(self, query: T) -> SelectBuilder<'a, S, SelectFromSet, T>
161 where
162 T: ToSQL<'a, SQLiteValue<'a>>,
163 {
164 SelectBuilder {
165 sql: self.sql.append(helpers::from(query)),
166 schema: PhantomData,
167 state: PhantomData,
168 table: PhantomData,
169 }
170 }
171}
172
173impl<'a, S, T> SelectBuilder<'a, S, SelectFromSet, T>
178where
179 T: SQLTable<'a, SQLiteValue<'a>>,
180{
181 #[inline]
183 pub fn join<U: IsInSchema<S> + SQLTable<'a, SQLiteValue<'a>>>(
184 self,
185 table: U,
186 condition: SQL<'a, SQLiteValue<'a>>,
187 ) -> SelectBuilder<'a, S, SelectJoinSet, T> {
188 SelectBuilder {
189 sql: self.sql.append(helpers::join(table, condition)),
190 schema: PhantomData,
191 state: PhantomData,
192 table: PhantomData,
193 }
194 }
195
196 join_impl!();
197
198 #[inline]
199 pub fn r#where(
200 self,
201 condition: SQL<'a, SQLiteValue<'a>>,
202 ) -> SelectBuilder<'a, S, SelectWhereSet, T> {
203 SelectBuilder {
204 sql: self.sql.append(helpers::r#where(condition)),
205 schema: PhantomData,
206 state: PhantomData,
207 table: PhantomData,
208 }
209 }
210
211 pub fn group_by(
213 self,
214 expressions: Vec<SQL<'a, SQLiteValue<'a>>>,
215 ) -> SelectBuilder<'a, S, SelectGroupSet, T> {
216 SelectBuilder {
217 sql: self.sql.append(helpers::group_by(expressions)),
218 schema: PhantomData,
219 state: PhantomData,
220 table: PhantomData,
221 }
222 }
223
224 #[inline]
226 pub fn limit(self, limit: usize) -> SelectBuilder<'a, S, SelectLimitSet, T> {
227 SelectBuilder {
228 sql: self.sql.append(helpers::limit(limit)),
229 schema: PhantomData,
230 state: PhantomData,
231 table: PhantomData,
232 }
233 }
234
235 #[inline]
237 pub fn offset(self, offset: usize) -> SelectBuilder<'a, S, SelectOffsetSet, T> {
238 SelectBuilder {
239 sql: self.sql.append(helpers::offset(offset)),
240 schema: PhantomData,
241 state: PhantomData,
242 table: PhantomData,
243 }
244 }
245
246 #[inline]
248 pub fn order_by<TOrderBy>(
249 self,
250 expressions: TOrderBy,
251 ) -> SelectBuilder<'a, S, SelectOrderSet, T>
252 where
253 TOrderBy: drizzle_core::ToSQL<'a, SQLiteValue<'a>>,
254 {
255 SelectBuilder {
256 sql: self.sql.append(helpers::order_by(expressions)),
257 schema: PhantomData,
258 state: PhantomData,
259 table: PhantomData,
260 }
261 }
262}
263
264impl<'a, S, T> SelectBuilder<'a, S, SelectJoinSet, T> {
269 #[inline]
271 pub fn r#where(
272 self,
273 condition: SQL<'a, SQLiteValue<'a>>,
274 ) -> SelectBuilder<'a, S, SelectWhereSet, T> {
275 SelectBuilder {
276 sql: self.sql.append(crate::helpers::r#where(condition)),
277 schema: PhantomData,
278 state: PhantomData,
279 table: PhantomData,
280 }
281 }
282 #[inline]
284 pub fn order_by<TOrderBy>(
285 self,
286 expressions: TOrderBy,
287 ) -> SelectBuilder<'a, S, SelectOrderSet, T>
288 where
289 TOrderBy: drizzle_core::ToSQL<'a, SQLiteValue<'a>>,
290 {
291 SelectBuilder {
292 sql: self.sql.append(helpers::order_by(expressions)),
293 schema: PhantomData,
294 state: PhantomData,
295 table: PhantomData,
296 }
297 }
298 #[inline]
300 pub fn join<U: IsInSchema<S> + SQLTable<'a, SQLiteValue<'a>>>(
301 self,
302 table: U,
303 condition: SQL<'a, SQLiteValue<'a>>,
304 ) -> SelectBuilder<'a, S, SelectJoinSet, T> {
305 SelectBuilder {
306 sql: self.sql.append(helpers::join(table, condition)),
307 schema: PhantomData,
308 state: PhantomData,
309 table: PhantomData,
310 }
311 }
312 join_impl!();
313}
314
315impl<'a, S, T> SelectBuilder<'a, S, SelectWhereSet, T> {
320 pub fn group_by(
322 self,
323 expressions: Vec<SQL<'a, SQLiteValue<'a>>>,
324 ) -> SelectBuilder<'a, S, SelectGroupSet, T> {
325 SelectBuilder {
326 sql: self.sql.append(helpers::group_by(expressions)),
327 schema: PhantomData,
328 state: PhantomData,
329 table: PhantomData,
330 }
331 }
332
333 pub fn order_by<TOrderBy>(
335 self,
336 expressions: TOrderBy,
337 ) -> SelectBuilder<'a, S, SelectOrderSet, T>
338 where
339 TOrderBy: drizzle_core::ToSQL<'a, SQLiteValue<'a>>,
340 {
341 SelectBuilder {
342 sql: self.sql.append(helpers::order_by(expressions)),
343 schema: PhantomData,
344 state: PhantomData,
345 table: PhantomData,
346 }
347 }
348
349 pub fn limit(self, limit: usize) -> SelectBuilder<'a, S, SelectLimitSet, T> {
351 SelectBuilder {
352 sql: self.sql.append(helpers::limit(limit)),
353 schema: PhantomData,
354 state: PhantomData,
355 table: PhantomData,
356 }
357 }
358}
359
360impl<'a, S, T> SelectBuilder<'a, S, SelectGroupSet, T> {
365 pub fn having(
367 self,
368 condition: SQL<'a, SQLiteValue<'a>>,
369 ) -> SelectBuilder<'a, S, SelectGroupSet, T> {
370 SelectBuilder {
371 sql: self.sql.append(helpers::having(condition)),
372 schema: PhantomData,
373 state: PhantomData,
374 table: PhantomData,
375 }
376 }
377
378 pub fn order_by<TOrderBy>(
380 self,
381 expressions: TOrderBy,
382 ) -> SelectBuilder<'a, S, SelectOrderSet, T>
383 where
384 TOrderBy: drizzle_core::ToSQL<'a, SQLiteValue<'a>>,
385 {
386 SelectBuilder {
387 sql: self.sql.append(helpers::order_by(expressions)),
388 schema: PhantomData,
389 state: PhantomData,
390 table: PhantomData,
391 }
392 }
393}
394
395impl<'a, S, T> SelectBuilder<'a, S, SelectOrderSet, T> {
400 pub fn limit(self, limit: usize) -> SelectBuilder<'a, S, SelectLimitSet, T> {
402 SelectBuilder {
403 sql: self.sql.append(helpers::limit(limit)),
404 schema: PhantomData,
405 state: PhantomData,
406 table: PhantomData,
407 }
408 }
409}
410
411impl<'a, S, T> SelectBuilder<'a, S, SelectLimitSet, T> {
416 pub fn offset(self, offset: usize) -> SelectBuilder<'a, S, SelectOffsetSet, T> {
418 SelectBuilder {
419 sql: self.sql.append(helpers::offset(offset)),
420 schema: PhantomData,
421 state: PhantomData,
422 table: PhantomData,
423 }
424 }
425}