1use crate::{
6 expr::{Condition, ConditionHolder, IntoCondition, SimpleExpr},
7 types::{
8 ColumnRef, DynIden, IntoColumnRef, IntoIden, IntoTableRef, JoinExpr, JoinType, Order,
9 OrderExpr, TableRef, WindowStatement,
10 },
11 value::{IntoValue, Value, Values},
12};
13
14use super::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
15
16#[derive(Debug, Clone, Default)]
34pub struct SelectStatement {
35 pub(crate) ctes: Vec<CommonTableExpr>,
36 pub(crate) distinct: Option<SelectDistinct>,
37 pub(crate) selects: Vec<SelectExpr>,
38 pub(crate) from: Vec<TableRef>,
39 pub(crate) join: Vec<JoinExpr>,
40 pub(crate) r#where: ConditionHolder,
41 pub(crate) groups: Vec<SimpleExpr>,
42 pub(crate) having: ConditionHolder,
43 pub(crate) unions: Vec<(UnionType, SelectStatement)>,
44 pub(crate) orders: Vec<OrderExpr>,
45 pub(crate) limit: Option<Value>,
46 pub(crate) offset: Option<Value>,
47 pub(crate) lock: Option<LockClause>,
48 pub(crate) windows: Vec<(DynIden, WindowStatement)>,
49}
50
51#[derive(Debug, Clone)]
55pub struct CommonTableExpr {
56 pub(crate) name: DynIden,
58 pub(crate) query: Box<SelectStatement>,
60 pub(crate) recursive: bool,
62}
63
64#[derive(Debug, Clone)]
66#[non_exhaustive]
67pub enum SelectDistinct {
68 All,
70 Distinct,
72 DistinctRow,
74 DistinctOn(Vec<ColumnRef>),
76}
77
78#[derive(Debug, Clone)]
80pub struct SelectExpr {
81 pub expr: SimpleExpr,
83 pub alias: Option<DynIden>,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89#[non_exhaustive]
90pub enum LockType {
91 Update,
93 NoKeyUpdate,
95 Share,
97 KeyShare,
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
103#[non_exhaustive]
104pub enum LockBehavior {
105 Nowait,
107 SkipLocked,
109}
110
111#[allow(dead_code)]
114#[derive(Debug, Clone)]
115pub struct LockClause {
116 pub(crate) r#type: LockType,
117 pub(crate) tables: Vec<TableRef>,
118 pub(crate) behavior: Option<LockBehavior>,
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123#[non_exhaustive]
124pub enum UnionType {
125 Intersect,
127 Distinct,
129 Except,
131 All,
133}
134
135impl<T> From<T> for SelectExpr
136where
137 T: Into<SimpleExpr>,
138{
139 fn from(expr: T) -> Self {
140 SelectExpr {
141 expr: expr.into(),
142 alias: None,
143 }
144 }
145}
146
147impl SelectStatement {
148 pub fn new() -> Self {
150 Self::default()
151 }
152
153 pub fn take(&mut self) -> Self {
155 Self {
156 ctes: std::mem::take(&mut self.ctes),
157 distinct: self.distinct.take(),
158 selects: std::mem::take(&mut self.selects),
159 from: std::mem::take(&mut self.from),
160 join: std::mem::take(&mut self.join),
161 r#where: std::mem::replace(&mut self.r#where, ConditionHolder::new()),
162 groups: std::mem::take(&mut self.groups),
163 having: std::mem::replace(&mut self.having, ConditionHolder::new()),
164 unions: std::mem::take(&mut self.unions),
165 orders: std::mem::take(&mut self.orders),
166 limit: self.limit.take(),
167 offset: self.offset.take(),
168 lock: self.lock.take(),
169 windows: std::mem::take(&mut self.windows),
170 }
171 }
172
173 pub fn column<C>(&mut self, col: C) -> &mut Self
188 where
189 C: IntoColumnRef,
190 {
191 self.selects.push(SelectExpr {
192 expr: SimpleExpr::Column(col.into_column_ref()),
193 alias: None,
194 });
195 self
196 }
197
198 pub fn columns<I, C>(&mut self, cols: I) -> &mut Self
210 where
211 I: IntoIterator<Item = C>,
212 C: IntoColumnRef,
213 {
214 for col in cols {
215 self.column(col);
216 }
217 self
218 }
219
220 pub fn expr<E>(&mut self, expr: E) -> &mut Self
232 where
233 E: Into<SimpleExpr>,
234 {
235 self.selects.push(SelectExpr {
236 expr: expr.into(),
237 alias: None,
238 });
239 self
240 }
241
242 pub fn expr_as<E, A>(&mut self, expr: E, alias: A) -> &mut Self
254 where
255 E: Into<SimpleExpr>,
256 A: IntoIden,
257 {
258 self.selects.push(SelectExpr {
259 expr: expr.into(),
260 alias: Some(alias.into_iden()),
261 });
262 self
263 }
264
265 pub fn from<T>(&mut self, tbl: T) -> &mut Self
279 where
280 T: IntoTableRef,
281 {
282 self.from.push(tbl.into_table_ref());
283 self
284 }
285
286 pub fn from_as<T, A>(&mut self, tbl: T, alias: A) -> &mut Self
290 where
291 T: IntoIden,
292 A: IntoIden,
293 {
294 self.from
295 .push(TableRef::TableAlias(tbl.into_iden(), alias.into_iden()));
296 self
297 }
298
299 pub fn from_subquery(&mut self, query: SelectStatement, alias: impl IntoIden) -> &mut Self {
303 self.from
304 .push(TableRef::SubQuery(Box::new(query), alias.into_iden()));
305 self
306 }
307
308 pub fn clear_selects(&mut self) -> &mut Self {
310 self.selects.clear();
311 self
312 }
313
314 pub fn join<T, C>(&mut self, join: JoinType, tbl: T, condition: C) -> &mut Self
332 where
333 T: IntoTableRef,
334 C: IntoCondition,
335 {
336 self.join.push(JoinExpr {
337 join,
338 table: tbl.into_table_ref(),
339 on: Some(crate::types::JoinOn::Condition(condition.into_condition())),
340 });
341 self
342 }
343
344 pub fn left_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
359 where
360 T: IntoTableRef,
361 C: IntoCondition,
362 {
363 self.join(JoinType::LeftJoin, tbl, condition)
364 }
365
366 pub fn right_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
368 where
369 T: IntoTableRef,
370 C: IntoCondition,
371 {
372 self.join(JoinType::RightJoin, tbl, condition)
373 }
374
375 pub fn full_outer_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
377 where
378 T: IntoTableRef,
379 C: IntoCondition,
380 {
381 self.join(JoinType::FullOuterJoin, tbl, condition)
382 }
383
384 pub fn inner_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
386 where
387 T: IntoTableRef,
388 C: IntoCondition,
389 {
390 self.join(JoinType::InnerJoin, tbl, condition)
391 }
392
393 pub fn cross_join<T>(&mut self, tbl: T) -> &mut Self
395 where
396 T: IntoTableRef,
397 {
398 self.join.push(JoinExpr {
399 join: JoinType::CrossJoin,
400 table: tbl.into_table_ref(),
401 on: None,
402 });
403 self
404 }
405
406 pub fn and_where<C>(&mut self, condition: C) -> &mut Self
420 where
421 C: IntoCondition,
422 {
423 self.r#where.add_and(condition);
424 self
425 }
426
427 pub fn cond_where(&mut self, condition: Condition) -> &mut Self {
429 self.r#where.add_and(condition);
430 self
431 }
432
433 pub fn group_by<C>(&mut self, col: C) -> &mut Self
449 where
450 C: IntoColumnRef,
451 {
452 self.groups.push(SimpleExpr::Column(col.into_column_ref()));
453 self
454 }
455
456 pub fn group_by_col<C>(&mut self, col: C) -> &mut Self
458 where
459 C: IntoColumnRef,
460 {
461 self.group_by(col)
462 }
463
464 pub fn group_by_columns<I, C>(&mut self, cols: I) -> &mut Self
466 where
467 I: IntoIterator<Item = C>,
468 C: IntoColumnRef,
469 {
470 for col in cols {
471 self.group_by(col);
472 }
473 self
474 }
475
476 pub fn and_having<C>(&mut self, condition: C) -> &mut Self
493 where
494 C: IntoCondition,
495 {
496 self.having.add_and(condition);
497 self
498 }
499
500 pub fn cond_having(&mut self, condition: Condition) -> &mut Self {
502 self.having.add_and(condition);
503 self
504 }
505
506 pub fn order_by<C>(&mut self, col: C, order: Order) -> &mut Self
521 where
522 C: IntoColumnRef,
523 {
524 use crate::types::OrderExprKind;
525 self.orders.push(OrderExpr {
526 expr: OrderExprKind::Expr(Box::new(SimpleExpr::Column(col.into_column_ref()))),
527 order,
528 nulls: None,
529 });
530 self
531 }
532
533 pub fn order_by_expr<E>(&mut self, expr: E, order: Order) -> &mut Self
535 where
536 E: Into<SimpleExpr>,
537 {
538 use crate::types::OrderExprKind;
539 self.orders.push(OrderExpr {
540 expr: OrderExprKind::Expr(Box::new(expr.into())),
541 order,
542 nulls: None,
543 });
544 self
545 }
546
547 pub fn limit<V>(&mut self, limit: V) -> &mut Self
561 where
562 V: IntoValue,
563 {
564 self.limit = Some(limit.into_value());
565 self
566 }
567
568 pub fn offset<V>(&mut self, offset: V) -> &mut Self
581 where
582 V: IntoValue,
583 {
584 self.offset = Some(offset.into_value());
585 self
586 }
587
588 pub fn distinct(&mut self) -> &mut Self {
603 self.distinct = Some(SelectDistinct::Distinct);
604 self
605 }
606
607 pub fn distinct_on<I, C>(&mut self, cols: I) -> &mut Self
609 where
610 I: IntoIterator<Item = C>,
611 C: IntoColumnRef,
612 {
613 let cols: Vec<ColumnRef> = cols.into_iter().map(|c| c.into_column_ref()).collect();
614 self.distinct = Some(SelectDistinct::DistinctOn(cols));
615 self
616 }
617
618 pub fn union(&mut self, query: SelectStatement) -> &mut Self {
622 self.unions.push((UnionType::Distinct, query));
623 self
624 }
625
626 pub fn union_all(&mut self, query: SelectStatement) -> &mut Self {
628 self.unions.push((UnionType::All, query));
629 self
630 }
631
632 pub fn intersect(&mut self, query: SelectStatement) -> &mut Self {
634 self.unions.push((UnionType::Intersect, query));
635 self
636 }
637
638 pub fn except(&mut self, query: SelectStatement) -> &mut Self {
640 self.unions.push((UnionType::Except, query));
641 self
642 }
643
644 pub fn with_cte<N>(&mut self, name: N, query: SelectStatement) -> &mut Self
665 where
666 N: IntoIden,
667 {
668 self.ctes.push(CommonTableExpr {
669 name: name.into_iden(),
670 query: Box::new(query),
671 recursive: false,
672 });
673 self
674 }
675
676 pub fn with_recursive_cte<N>(&mut self, name: N, query: SelectStatement) -> &mut Self
709 where
710 N: IntoIden,
711 {
712 self.ctes.push(CommonTableExpr {
713 name: name.into_iden(),
714 query: Box::new(query),
715 recursive: true,
716 });
717 self
718 }
719
720 pub fn window_as<T>(&mut self, name: T, window: WindowStatement) -> &mut Self
749 where
750 T: IntoIden,
751 {
752 self.windows.push((name.into_iden(), window));
753 self
754 }
755
756 pub fn lock(&mut self, lock_type: LockType) -> &mut Self {
760 self.lock = Some(LockClause {
761 r#type: lock_type,
762 tables: Vec::new(),
763 behavior: None,
764 });
765 self
766 }
767
768 pub fn lock_exclusive(&mut self) -> &mut Self {
770 self.lock(LockType::Update)
771 }
772
773 pub fn lock_shared(&mut self) -> &mut Self {
775 self.lock(LockType::Share)
776 }
777
778 pub fn apply_if<T, F>(&mut self, val: Option<T>, func: F) -> &mut Self
782 where
783 F: FnOnce(&mut Self, T),
784 {
785 if let Some(val) = val {
786 func(self, val);
787 }
788 self
789 }
790
791 pub fn conditions<T, F>(&mut self, b: bool, if_true: T, if_false: F) -> &mut Self
793 where
794 T: FnOnce(&mut Self),
795 F: FnOnce(&mut Self),
796 {
797 if b {
798 if_true(self)
799 } else {
800 if_false(self)
801 }
802 self
803 }
804}
805
806impl QueryStatementBuilder for SelectStatement {
807 fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, Values) {
808 use crate::backend::{
809 MySqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder,
810 };
811 use std::any::Any;
812
813 let any_builder = query_builder as &dyn Any;
814
815 if let Some(pg) = any_builder.downcast_ref::<PostgresQueryBuilder>() {
816 return pg.build_select(self);
817 }
818
819 if let Some(mysql) = any_builder.downcast_ref::<MySqlQueryBuilder>() {
820 return mysql.build_select(self);
821 }
822
823 if let Some(sqlite) = any_builder.downcast_ref::<SqliteQueryBuilder>() {
824 return sqlite.build_select(self);
825 }
826
827 panic!(
828 "Unsupported query builder type. Use PostgresQueryBuilder, MySqlQueryBuilder, or SqliteQueryBuilder."
829 );
830 }
831}
832
833impl QueryStatementWriter for SelectStatement {}